driver-gen/xml-lib: Search for version header files in the correct dir
[driver-gen.git] / driverGen.c
blob940fdb13ab8569186d190ac5e5ae3a7dddf289d6
1 /**
2 * @file driverGen.c
4 * @brief Pulling everything together.
6 * Device Driver Generator (aka DriverGen) tool designed to produce
7 * device drivers for a given architecture based on an abstract description
8 * of a piece of hardware.
10 * @author Copyright (C) 2002 CERN. Stuart Baird
11 * @author Copyright (C) 2003 CERN. Alain Gagnaire
12 * @author Copyright (C) 2003 - 2010 CERN. Georgievskiy Yury <ygeorgie@cern.ch>
14 * @date Created on 27/02/2004
16 * @section license_sec License
17 * Released under the GPL
19 #define _GNU_SOURCE /* asprintf rocks */
20 #include <getopt.h>
21 #include "driverGen.h"
22 #include "utilities.h"
23 #include "serviceOptions.h"
24 #include "dg-version.h"
25 #include "dg-git-lib.h"
27 struct mdescr dgmd = { 0 }; /* Driver-Gen Module Description */
29 bool verboseMode; /* denotes verbose driver generation */
30 static dgopt genOpt; /* possible command line options */
31 static srvarg glob_srv_arg; /* possible service option arguments */
32 char *driverName; /* Driver Name. Exactly as in the DataBase */
33 char *busType; /* bus type. 'vme' or 'pci' */
34 time_t mod_creation_time; /* driver creation time of the currently
35 processed module */
37 /* supported buses */
38 static char *allBuses[] = {
39 "vme",
40 "VME",
41 "pci",
42 "PCI",
43 NULL
46 /* supported command line options */
47 static struct option allLongOptions[] = {
48 { "git", no_argument, NULL, 'g' },
49 { "gall", no_argument, NULL, 'a' },
50 { "ginfo", no_argument, NULL, 'i' },
51 { "general", required_argument, NULL, 'e' },
52 { "verbose", no_argument, NULL, 'n' },
53 { "srv", required_argument, NULL, 's' }, /* see 'serviceOptions.h'
54 for more information */
55 { "dir", required_argument, NULL, 'd' },
56 { "version", no_argument, NULL, 'v' },
57 { "help", no_argument, NULL, 'h' },
59 .name = 0,
60 .has_arg = no_argument, /* 0 */
61 .flag = 0,
62 .val = 0
66 static int CheckAndPrepareRegs(RegisterDef_t *, int, VmeInfo_t *);
67 static int CheckAndPrepareBlocks(BlockDef_t *, int);
68 static void SortRegisters(RegisterDef_t *, VmeInfo_t *, int, int);
69 static int LessThan(RegisterDef_t *, RegisterDef_t *);
70 static int GreaterThan(RegisterDef_t *, RegisterDef_t *);
71 static void SortBlocks(BlockDef_t *, int, int);
72 static bool CheckBusType(char *);
73 static void DisplayUsage(char *);
74 static void ParseProgArgs(int, char *[], struct mdescr *);
75 static void free_md(struct mdescr *);
77 int main(int argc, char *argv[], char *envp[])
79 int numRegisters;
80 int numBlocks;
81 rstat result;
82 RegisterDef_t registers[MAX_REG] = { {0} };
83 BlockDef_t blocks[MAX_BLK] = { {0} };
84 PciInfo_t pciInfo;
85 VmeInfo_t vmeInfo;
87 time(&mod_creation_time);
88 printf("%s <vers. %s> started on %s\n", basename(argv[0]), dg_version,
89 ctime(&mod_creation_time));
91 /* Init default parameters */
92 vmeInfo.CheckRegister = -1; /* no checking register */
93 verboseMode = FALSE; /* by default - no verbose mode */
95 ParseProgArgs(argc, argv, &dgmd); /* check if provided params are valid */
97 /* init global template values for further use */
98 TranslationInit(driverName, busType);
100 /* setup Master installation directory */
101 get_mid(&dgmd);
103 /* if only general shared code should be build */
104 if (genOpt == OPT_G_SHARED) {
105 BuildGeneralCode();
106 printf("%s: All done.\n", basename(argv[0]));
107 exit(EXIT_SUCCESS);
110 /* if it's one of the service calls */
111 if (genOpt == OPT_G_SERVICE) {
112 if (ProcessSrvOpt(glob_srv_arg, basename(argv[0]))) {
113 printf("%s: service option processing fails\n",
114 argv[0]);
115 exit(EXIT_FAILURE);
116 } else {
117 printf("%s: service option processing done.\n",
118 argv[0]);
119 exit(EXIT_SUCCESS);
123 /* get block configuration from database */
124 if (!(numBlocks = GetBlockConfig(driverName, blocks, argv[0]))) {
125 fprintf(stderr, "%s No Blocks found for %s Module\n", ERROR_MSG,
126 driverName);
127 exit(EXIT_FAILURE);
130 /* check if block configuration is correct */
131 if (CheckAndPrepareBlocks(blocks, numBlocks) != DRIVER_GEN_OK)
132 exit(EXIT_FAILURE);
134 /* get register configuration from database */
135 numRegisters = GetRegisterConfig(driverName, registers, blocks,
136 numBlocks, argv[0]);
137 if (!numRegisters) {
138 fprintf(stderr, "%s No Registers found for %s Module\n",
139 ERROR_MSG, driverName);
140 exit(EXIT_FAILURE);
143 /* check if register configuration is correct */
144 if (CheckAndPrepareRegs(registers, numRegisters, &vmeInfo) !=
145 DRIVER_GEN_OK)
146 exit(EXIT_FAILURE);
148 /* we need to compute block sizes and their register amount */
149 set_extra_block_data(registers);
151 /* get general board information from the database */
152 if (!strcmp(TranslationGetBus(), "VME"))
153 result = GetVmeInfo(driverName, &vmeInfo);
154 else
155 result = GetPciInfo(driverName, &pciInfo);
157 if (result)
158 exit(EXIT_FAILURE); /* 1 */
160 /* setup Module source directory */
161 get_msd(&dgmd);
163 /* now we can start Driver/Simulator code generation */
164 if (!strcmp(TranslationGetBus(), "VME")) { /* we need VME driver */
165 switch (genOpt) {
166 case OPT_G_IT:
167 if (do_git_vme_driver(driverName, &dgmd, registers, numRegisters,
168 blocks, numBlocks, &vmeInfo))
169 exit(EXIT_FAILURE);
170 break;
171 case OPT_G_ALL: /* generate all, include user-defined files */
172 printf("Creating %s source code directory.\n", driverName);
173 GenerateVmeDriver(registers, numRegisters, blocks,
174 numBlocks, &vmeInfo);
175 break;
176 case OPT_G_INFO: /* generate only info files */
177 printf("Creating %s source code directory.\n", driverName);
178 GenerateVmeInfoFile(registers, numRegisters, blocks,
179 numBlocks, &vmeInfo);
180 break;
181 default:
182 FATAL_ERR();
183 break; /* not reached */
185 } else { /* we need PCI driver */
186 switch (genOpt) {
187 case OPT_G_IT:
188 /* TODO */
189 do_git_pci_driver(driverName, &dgmd, registers, numRegisters,
190 blocks, numBlocks, &pciInfo);
191 break;
192 case OPT_G_ALL: /* generate all, include user-defined files */
193 printf("Creating %s source code directory.\n", driverName);
194 GenerateDrmDriver(registers, numRegisters, blocks,
195 numBlocks, &pciInfo);
196 break;
197 case OPT_G_INFO: /* generate only install files */
198 printf("Creating %s source code directory.\n", driverName);
199 /* TODO. Should be removed. */
200 GenerateDrmInstallFilesOLD(&pciInfo, blocks, numBlocks);
201 break;
202 default:
203 FATAL_ERR();
204 break; /* not reached */
208 free_md(&dgmd);
209 printf("All done.\n");
210 exit(EXIT_SUCCESS); /* 0 */
214 * @brief Checks if module configuration is correct and supported.
216 * @param registers -- register description
217 * @param numRegisters -- register amount
218 * @param vmeInfo -- @b VME description
220 * @return DRIVER_GEN_OK - if configuration is ok.
221 * @return DRIVER_GEN_BAD - othervise.
223 static int CheckAndPrepareRegs(RegisterDef_t * registers, int numRegisters,
224 VmeInfo_t * vmeInfo)
226 int i, j;
227 int badConfig = DRIVER_GEN_OK;
228 int mappedAddr = 0; /* checked address range */
229 int regDepth; /* register depth, in elements */
231 for (i = 0; i < numRegisters; i++) { /* Sanitise register definition */
232 StrToLower(registers[i].size);
233 StrToLower(registers[i].mode);
234 registers[i].rar = 0;
235 for (j = 0; j < strlen(registers[i].mode); j++) {
236 if (registers[i].mode[j] == 'w') {
237 registers[i].rar |= AMWR;
238 } else if (registers[i].mode[j] == 'r') {
239 registers[i].rar |= AMRD;
240 } else if (registers[i].mode[j] == 'e') {
241 registers[i].rar |= AMEX;
242 } else if (registers[i].mode[j] == 'c') {
243 vmeInfo->CheckRegister = i;
244 } else {
245 badConfig = DRIVER_GEN_BAD;
246 fprintf(stderr, "%s Register '%s' has unknown"
247 " access mode '%c'\n",
248 ERROR_MSG, registers[i].name,
249 registers[i].mode[j]);
253 strcpy(registers[i].upperName, registers[i].name);
254 StrToUpper(registers[i].upperName);
256 if (!strcmp(registers[i].size, "char"))
257 registers[i].regSize = SZCHAR;
258 else if (!strcmp(registers[i].size, "short"))
259 registers[i].regSize = SZSHORT;
260 else if (!strcmp(registers[i].size, "long"))
261 registers[i].regSize = SZLONG;
262 else {
263 badConfig = DRIVER_GEN_BAD;
264 fprintf(stderr, "%s Register '%s' has incorrect size"
265 " name '%s'\n",
266 ERROR_MSG, registers[i].name,
267 registers[i].size);
270 /* Check if the data is valid */
271 if (registers[i].timeLoop < 0) {
272 badConfig = DRIVER_GEN_BAD;
273 fprintf(stderr, "%s Register '%s' has a negative"
274 " timeloop %d\n",
275 ERROR_MSG, registers[i].name,
276 registers[i].timeLoop);
279 for (j = 0; j < strlen(registers[i].name); j++)
280 if (isspace(registers[i].name[j]))
281 /* replace wite spaces with underscore */
282 registers[i].name[j] = '_';
284 for (j = i + 1; j < numRegisters; j++)
285 if (!strcmp(registers[i].name, registers[j].name)) {
286 badConfig = DRIVER_GEN_BAD;
287 fprintf(stderr, "%s Register definitions %d"
288 " and %d share the name \"%s\"\n",
289 ERROR_MSG, i, j, registers[i].name);
292 if (registers[i].rar > AMEX) {
293 fprintf(stderr, "%s Register '%s' has a conflicting"
294 " access mode '%s'\n",
295 ERROR_MSG, registers[i].name,
296 registers[i].mode);
297 sprintf(registers[i].mode, "e");
298 registers[i].rar = AMEX;
301 if ((!registers[i].blockP)) {
302 badConfig = DRIVER_GEN_BAD;
303 fprintf(stderr, "%s Register '%s' doesn't belong to"
304 " any block\n",
305 ERROR_MSG, registers[i].name);
308 if (registers[i].offset < 0) {
309 badConfig = DRIVER_GEN_BAD;
310 fprintf(stderr, "%s Register '%s' has negative offset"
311 " value '0x%x'\n",
312 ERROR_MSG, registers[i].name,
313 registers[i].offset);
315 } /* end of 'for' */
317 if (badConfig == DRIVER_GEN_BAD)
318 return badConfig;
320 /* sort registers by their address */
321 SortRegisters(registers, vmeInfo, 0, numRegisters - 1);
323 for (i = 0; i < numRegisters - 1; i++) {
325 if (registers[i].depth <= 0)
326 regDepth = 1;
327 else
328 regDepth = registers[i].depth;
330 /* check registers that belong to the same block only */
331 if (registers[i].blockP->blockID ==
332 registers[i + 1].blockP->blockID) {
333 /* check if there is duplicate register addresses
334 in the same block */
335 if (registers[i].offset == registers[i + 1].offset) {
336 badConfig = DRIVER_GEN_BAD;
337 fprintf(stderr, "%s Registers '%s' and '%s' in"
338 " Block#%d have the same offset %#x\n",
339 ERROR_MSG, registers[i].name,
340 registers[i + 1].name,
341 registers[i].blockP->blockID,
342 registers[i].offset);
344 mappedAddr =
345 registers[i].offset +
346 registers[i].regSize * regDepth;
347 if (mappedAddr > registers[i + 1].offset) {
348 fprintf(stderr, "%s Overlapping between '%s'"
349 " and '%s' register massives\n"
350 "\tdetected in Block#%d. Incorrect "
351 "device memory mapping. Try to "
352 "change\n\tmemory layout in the Data"
353 " Base.\n",
354 ERROR_MSG, registers[i].name,
355 registers[i + 1].name,
356 registers[i].blockP->blockID);
357 badConfig = DRIVER_GEN_BAD;
359 } else {
360 mappedAddr = 0;
364 if (badConfig == DRIVER_GEN_BAD)
365 return badConfig;
367 /* Check if device checking address is provided */
368 if (vmeInfo->CheckRegister == -1) {
369 fprintf(stderr, "%sChecking Register is NOT provided!\n"
370 " Module availability will NOT be checked"
371 " during device driver\n installation!\n\n",
372 WARNING_MSG);
373 sleep(2); /* let user see it */
376 return badConfig;
380 * @brief Checks if block configuration is correct and supported.
382 * @param blocks -- block description
383 * @param numBlocks -- block amount
385 * @return DRIVER_GEN_OK - if configuration is ok.
386 * @return DRIVER_GEN_BAD - othervise.
388 static int CheckAndPrepareBlocks(BlockDef_t * blocks, int numBlocks)
390 int i;
391 int configState = DRIVER_GEN_OK;
393 for (i = 0; i < numBlocks; i++) {
394 if (blocks[i].blockID < 0) {
395 fprintf(stderr, "%s GetBlockConfig() has returned a"
396 " record with a negative block number\n",
397 ERROR_MSG);
398 configState = DRIVER_GEN_BAD;
401 if ((blocks[i].blkBaseAddr < 1) ||
402 (blocks[i].blkBaseAddr > 2)) {
403 fprintf(stderr, "%s Block#%d is associated with"
404 " invalid base address value '%d'\n",
405 ERROR_MSG, blocks[i].blockID,
406 blocks[i].blkBaseAddr);
407 configState = DRIVER_GEN_BAD;
410 if (blocks[i].offset < 0) {
411 fprintf(stderr, "%s Block#%d has a negative offset"
412 " value\n",
413 ERROR_MSG, blocks[i].blockID);
414 configState = DRIVER_GEN_BAD;
418 if (configState == DRIVER_GEN_OK) {
419 SortBlocks(blocks, 0, numBlocks - 1);
420 for (i = 0; i < numBlocks - 1; i++)
421 if (blocks[i].blockID == blocks[i + 1].blockID) {
422 fprintf(stderr, "%s GetBlockConfig() has"
423 " returned two records with block ID's"
424 " equals to %d\n",
425 ERROR_MSG, blocks[i].blockID);
426 configState = DRIVER_GEN_BAD;
430 return configState;
434 * @brief Sort registers by their block indexes && addresses.
436 * @param registers -- register description table
437 * @param vmeInfo -- VME description
438 * @param low -- lowest index
439 * @param high -- highest index
441 static void SortRegisters(RegisterDef_t *registers, VmeInfo_t *vmeInfo,
442 int low, int high)
444 int left, right;
445 RegisterDef_t buffer;
446 RegisterDef_t *median;
448 if (high > low) {
449 left = low;
450 right = high;
451 median = &registers[low];
453 while (right >= low) {
454 while (LessThan(&(registers[left]), median))
455 left++;
457 while (GreaterThan(&(registers[right]), median))
458 right--;
460 if (left > right)
461 break;
463 buffer = registers[left];
464 registers[left] = registers[right];
465 registers[right] = buffer;
467 /* move checking register index */
468 if (vmeInfo->CheckRegister == left)
469 vmeInfo->CheckRegister = right;
470 else if (vmeInfo->CheckRegister == right)
471 vmeInfo->CheckRegister = left;
473 left++;
474 right--;
477 SortRegisters(registers, vmeInfo, low, right);
478 SortRegisters(registers, vmeInfo, left, high);
483 * @brief Check if register a is smaller then register b
485 * @param a -- reg descr
486 * @param b -- reg descr
488 * @return 1 - if first regID is smaller then the second one.
489 * @return 0 - otherwise.
491 static int LessThan(RegisterDef_t *a, RegisterDef_t *b)
493 if (a->blockP->blockID < b->blockP->blockID)
494 return 1;
495 else if ((a->blockP->blockID == b->blockP->blockID) &&
496 (a->offset < b->offset))
497 return 1;
498 else
499 return 0;
503 * @brief Check if register a is greater then register b
505 * @param a -- reg descr
506 * @param b -- reg descr
508 * @return 1 - if first regID is greater then the second one.
509 * @return 0 - otherwise.
511 static int GreaterThan(RegisterDef_t *a, RegisterDef_t *b)
513 if ((a->blockP->blockID == b->blockP->blockID)
514 && (a->offset == b->offset))
515 return 0;
516 else
517 return (!LessThan(a, b));
521 * @brief Sort blocks by their index
523 * @param blocks -- block description
524 * @param low -- low block idx
525 * @param high -- high block idx
527 * @return void
529 static void SortBlocks(BlockDef_t *blocks, int low, int high)
531 int left, right;
532 BlockDef_t buffer;
533 BlockDef_t *median;
535 if (high > low) {
536 left = low;
537 right = high;
538 median = &(blocks[low]);
540 while (right >= low) {
541 while (blocks[left].blockID < median->blockID)
542 left++;
544 while (blocks[right].blockID > median->blockID)
545 right--;
547 if (left > right)
548 break;
550 buffer = blocks[left];
551 blocks[left] = blocks[right];
552 blocks[right] = buffer;
553 left++;
554 right--;
557 SortBlocks(blocks, low, right);
558 SortBlocks(blocks, left, high);
563 * @brief Checks if the bus type parameter is correct.
565 * If it is not, than error is printed out on stderr.
567 * @param str -- string to check
569 * @return TRUE - if parameter is valid.
570 * @return FALSE - otherwise.
572 static bool CheckBusType(char *str)
574 bool res = FALSE;
575 char **ptr, errMsg[64];
577 ptr = allBuses;
578 snprintf(errMsg, sizeof(errMsg), "Bus type \'%s\' not supported.\n",
579 str);
581 while (*ptr) {
582 if (!(strcmp(*ptr, str))) { /* option matches */
583 res = TRUE;
584 break;
586 ptr++; /* move pointer */
589 if (!res)
590 fprintf(stderr, errMsg); /* printout error message. */
592 return (res);
596 * @brief Educate user
598 * @param progName -- program name
600 * @return void
602 static void DisplayUsage(char *progName)
604 progName = basename(progName);
605 printf("%s %s\n\n", progName, dg_version);
606 printf("Usage: %s <module_name> <bus> -g[it | all | info] "
607 "<-verbose> -d <root_dir>\n", progName);
608 printf(" %s <-general> <bus>\n", progName);
609 printf(" %s <-h> <--version> (to get help && version info)\n",
610 progName);
611 printf("where:\n");
613 /* module-name */
614 printf(" <module_name> %sCompulsory%s\n", WHITE_CLR, END_CLR);
615 printf(" It is the name of the module for which Driver/Simulator "
616 "should be generated.\n");
617 printf(" Should be exactly as in the DataBase. See DataBase for"
618 " more info about\n Module Names.\n\n");
620 /* bus */
621 printf(" <bus> %sCompulsory%s\n", WHITE_CLR, END_CLR);
622 printf(" Select the bus architecture supported by the card.\n");
623 printf(" Supported buses are 'pci' or 'vme'.\n\n");
625 /* '-g' mode description */
626 printf(" -g %sOptional%s\n"
627 " What to generate (if not provided -- default will be"
628 " used):\n", WHITE_CLR, END_CLR);
629 printf(" -g[all]\n"
630 " Generate complete driver framework\n");
631 printf(" -g[it] %sDefault%s\n"
632 " Generate git-controlled Driver, i.e. user-defined files"
633 " are generated\n"
634 " only if driver directory does not yet exist (otherwise"
635 " user-defined files\n"
636 " left intact), driver dir name doesn't have time prefix,"
637 " git-tag is\n"
638 " performed. (All files, that've got \"UserDefined\""
639 " subword in their\n"
640 " name -- are considered to be user-defined files)\n",
641 WHITE_CLR, END_CLR);
643 printf(" -g[info]\n"
644 " Generate only info file for current module.\n\n");
646 /* '-verbose' mode description */
647 printf(" <-verbose> %sOptional%s\n"
648 " This enables verbose driver/simulator source code"
649 " generation.\n"
650 " Useful for debugging purposes.\n\n", WHITE_CLR, END_CLR);
652 /* '-dir' mode description */
653 printf(" <-d> %sOptional%s\n"
654 " Change root directory, where generated driver source code"
655 " will reside.\n"
656 " Default one is 'genDriverDeposit'\n\n",
657 WHITE_CLR, END_CLR);
659 /* '-general' mode description */
660 printf(" <-general> %sOptional%s\n", WHITE_CLR, END_CLR);
661 printf(" Normal users should ignore this option.\n If all that you"
662 " want - is to generate a Driver/Simulator framework for a\n"
663 " given module, and you didn't make any changes in"
664 " installation procedure\n and library code (that is usially"
665 " the case), than you should ignore\n this option. Only"
666 " general purpose files (i.e. identical for all types of \n"
667 " Driver/Simulator) will be generated. These are module"
668 " Driver/Simulator\n installation and unistallaion programs,"
669 " 'DriverAccess' library and general\n header files. Normally,"
670 " general purpose part should be rebuild by 'driverGen'\n"
671 " software developer, and only in case of it's modification."
672 " Bus type (pci or\n vme) should be provided.\n\n");
674 /* show some examples examples */
675 printf("EXAMPLES: %s BNLDSP vme -gall\n"
676 " %s SHARED_CIBC vme\n\n",
677 progName, progName);
680 #define OPT_COLLIDE(__opt) \
681 ({ \
682 int __val; \
683 if (genOpt & (~__opt)) { \
684 genOpt = OPT_COLLIDE; \
685 __val = 1; \
686 } else \
687 __val = 0; \
688 __val; \
690 #define MAX_NON_OPT_ARGS 3 /* max non-option arguments amount */
693 * @brief Parses command line arguments.
695 * @param argc -- command line argument count
696 * @param argv -- command line argument array
697 * @param md -- module description
699 * @return void
701 static void ParseProgArgs(int argc, char *argv[], struct mdescr *md)
703 int cur_opt; /* currently parsed option */
704 char arg_mas[MAX_NON_OPT_ARGS][NAME_LEN]; /* hold all non-option
705 arguments */
706 int arg_cntr = 0; /* non-option arguments counter */
707 int expected_arg_amount = 0;
709 memset(arg_mas, 0, sizeof(arg_mas));
710 while (((cur_opt =
711 getopt_long_only(argc, argv, "-hv", allLongOptions,
712 NULL)) != EOF) && (genOpt != OPT_COLLIDE)
713 && (glob_srv_arg != SRV_ARG_ERROR) && (arg_cntr != 27051977)) {
714 switch (cur_opt) {
715 case 1: /* this is non-option arg */
716 if (arg_cntr == MAX_NON_OPT_ARGS) {
717 arg_cntr = 27051977;
718 break;
720 strncpy(arg_mas[arg_cntr], optarg, NAME_LEN);
721 arg_mas[arg_cntr][NAME_LEN - 1] = 0; /* safety
722 terminate */
723 ++arg_cntr;
724 break;
725 case 'h': /* user need help */
726 DisplayUsage(argv[0]);
727 exit(EXIT_SUCCESS); /* 0 */
728 break;
729 case 'g': /* generate driver, controlled by git */
730 if (OPT_COLLIDE(OPT_G_IT))
731 break;
732 genOpt = OPT_G_IT;
733 expected_arg_amount = 2;
734 md->isgit = 1;
735 break;
736 case 'a': /* generate full driver (include user part) */
737 if (OPT_COLLIDE(OPT_G_ALL))
738 break;
739 genOpt = OPT_G_ALL;
740 expected_arg_amount = 2;
741 break;
742 case 'i': /* only info file */
743 if (OPT_COLLIDE(OPT_G_INFO))
744 break;
745 genOpt = OPT_G_INFO;
746 expected_arg_amount = 2;
747 break;
748 case 'e': /* general part only (-general) */
749 if (OPT_COLLIDE(OPT_G_SHARED))
750 break;
751 genOpt = OPT_G_SHARED;
752 expected_arg_amount = 0;
753 busType = strdup(optarg); /* set bus type */
754 driverName = strdup("GENERAL"); /* set name for
755 general part */
756 break;
757 case 's': /* we have service option */
758 /* see serviceOptions.h for more info */
759 if (OPT_COLLIDE(OPT_G_SERVICE))
760 break;
761 genOpt = OPT_G_SERVICE;
762 /* they've got non-option arguments. set their amount */
763 if (!strcmp(optarg, "drvrvers")) {
764 expected_arg_amount = 3;
765 glob_srv_arg = SRV_VF_DRVR; /* Verion File for
766 the driver */
767 } else if (!strcmp(optarg, "simvers")) {
768 expected_arg_amount = 3;
769 glob_srv_arg = SRV_VF_SIM; /* Version File for
770 the simulator */
771 } else {
772 expected_arg_amount = 0;
773 glob_srv_arg = SRV_ARG_ERROR;
775 break;
776 case 'n': /* verbose printout during code generation */
777 verboseMode = TRUE;
778 break;
779 case 'd': /* root directory, where driver directory will be created */
780 asprintf(&md->mdn, "%s", optarg);
781 break;
782 case 'v': /* version string */
783 printf("%s [Compiled on %s %s]\n", dg_version,
784 __DATE__, __TIME__);
785 exit(EXIT_SUCCESS);
786 break;
787 case '?': /* wrong option */
788 default:
789 fprintf(stderr, "Wrong option.\n");
790 fprintf(stderr, "Try \'%s -h\' for more information.\n",
791 argv[0]);
792 exit(EXIT_FAILURE); /* 1 */
793 break;
797 if (genOpt == OPT_COLLIDE) { /* check for option colliding */
798 fprintf(stderr, "Option collision detected!\n");
799 fprintf(stderr, "Try \'%s -h\' for more information.\n",
800 argv[0]);
801 exit(EXIT_FAILURE); /* 1 */
804 if (!genOpt) { /* user didn't provide command line
805 option -- set default */
806 genOpt = OPT_G_IT; /* by default create git-controlled driver */
807 md->isgit = 1;
808 expected_arg_amount = 2;
811 if (glob_srv_arg == SRV_ARG_ERROR) { /* check service option argument */
812 fprintf(stderr, "Wrong service option argument.\n");
813 fprintf(stderr, "Try \'%s -h\' for more information.\n",
814 argv[0]);
815 exit(EXIT_FAILURE); /* 1 */
818 if (arg_cntr != expected_arg_amount) { /* check for argument amount */
819 fprintf(stderr, "Wrong arguments.\n");
820 fprintf(stderr, "Try \'%s -h\' for more information.\n",
821 argv[0]);
822 exit(EXIT_FAILURE); /* 1 */
825 /* now we handle all non-option arguments
826 (they are in 'arg_mas' massive) */
827 switch (genOpt) {
828 case OPT_G_IT:
829 if (git_check_version())
830 exit(EXIT_FAILURE);
831 case OPT_G_ALL:
832 case OPT_G_INFO:
833 driverName = strdup(arg_mas[0]); /* set DB driver name */
834 busType = strdup(arg_mas[1]); /* set bus type */
835 break;
836 case OPT_G_SHARED:
837 break; /* nothing to do */
838 case OPT_G_SERVICE:
839 switch (glob_srv_arg) {
840 case SRV_VF_DRVR:
841 case SRV_VF_SIM:
842 driverName = strdup(arg_mas[0]); /* set DB driver
843 name */
844 busType = strdup(arg_mas[1]); /* set bus type */
845 SetSrvOptArgs(glob_srv_arg, arg_mas[2]);
846 break;
847 default:
848 break;
850 default:
851 break;
854 if (!CheckBusType(busType)) { /* check 'Bus Type' */
855 fprintf(stderr, "Try \'%s -h\' for more information.\n",
856 argv[0]);
857 exit(EXIT_FAILURE); /* 1 */
860 if (!md->mdn)
861 asprintf(&md->mdn, "%s", DEFAULT_MASTER_DIR);
865 * @brief Free allocated resources of module description.
867 * @param md -- module description.
870 static void free_md(struct mdescr *md)
872 if (md->mdn)
873 free(md->mdn);