pax_global_header00006660000000000000000000000064132237637730014527gustar00rootroot0000000000000052 comment=541d75898159755eca81ec818edf70722f6834f9 libguytools2-2.0.5/000077500000000000000000000000001322376377300141715ustar00rootroot00000000000000libguytools2-2.0.5/COPYING000066400000000000000000000432541322376377300152340ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. libguytools2-2.0.5/changelog000066400000000000000000000041711322376377300160460ustar00rootroot00000000000000libguytools2 (2.0.5-1) unstable; urgency=low * Moved to Qt5 * Adapted to Debian 8 (Jessie) -- Guy Voncken Tue, 18 Jul 2017 12:00:00 +0200 libguytools2 (2.0.4-1) unstable; urgency=low * Removed arch specific code in toolsignal.cpp -- Guy Voncken Thu, 13 Jul 2015 16:00:00 +0200 libguytools2 (2.0.3-1) unstable; urgency=low * Corrected problem with trailing backslashes * Switched to my new developer email address -- Guy Voncken Thu, 30 Oct 2014 16:00:00 +0100 libguytools2 (2.0.2-1) unstable; urgency=low * Correctly handling decimal point for different locale settings in toolcfg * Some small signed/unsigned changes for cleaner linting * Copyright notices cleaned up -- Guy Voncken Tue, 17 Jul 2012 10:00:00 +0200 libguytools2 (2.0.1-1) unstable; urgency=low * Trunk released -- Guy Voncken Tue, 04 Aug 2010 11:30:00 +0200 libguytools2 (2.0.0beta1-1) unstable; urgency=low * Putting everything into only one lib * Some small changes for compilation under Ubuntu 10.04 -- Guy Voncken Fri, 02 Aug 2010 17:00:00 +0200 libguytools1 (1.1.0beta1-0) unstable; urgency=low * Preventing from repetitive messages if log file can't be opened * Debian packaging checked and corrected (again and again) * Using fopen64 for the log file, so that it may grow above any old limits * Build scripts made more portable (thanks to GIDA) * Debianisation changes by Mika -- Guy Voncken Tue, 18 Aug 2009 11:00:00 +0200 libguytools1 (1.0.3) unstable; urgency=low * Debian packaging checked and corrected -- Guy Voncken Wed, 08 Apr 2008 17:00:00 +0200 libguytools1 (1.0.2) unstable; urgency=low * Support for amd64 architecture -- Guy Voncken Wed, 16 Nov 2007 09:00:00 +0200 libguytools1 (1.0.1) unstable; urgency=low * Const type cleaned up. -- Guy Voncken Wed, 06 Jun 2007 16:25:08 +0200 libguytools1 (1.0.0) unstable; urgency=low * Initial release. -- Guy Voncken Wed, 06 Jun 2007 16:25:08 +0200 libguytools2-2.0.5/create_version_file.sh000077500000000000000000000003431322376377300205370ustar00rootroot00000000000000#!/bin/bash TOOLS_VERSION=`cat changelog debian/changelog 2>/dev/null | head -qn 1 ` TOOLS_VERSION="${TOOLS_VERSION%%)*}" TOOLS_VERSION="${TOOLS_VERSION##*(}" echo "VERSION = ${TOOLS_VERSION%%-*}" >libguytools_version.pro.inc libguytools2-2.0.5/include/000077500000000000000000000000001322376377300156145ustar00rootroot00000000000000libguytools2-2.0.5/include/toolcfg.h000066400000000000000000000211711322376377300174240ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Configuration utility // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLCFG_H__ #define __TOOLCFG_H__ /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef enum { CFGTYPE_PRESENCE, CFGTYPE_INTEGER, CFGTYPE_DOUBLE, CFGTYPE_STRING, CFGTYPE_SET, CFGTYPE_HMS, CFGTYPE_NULL } t_ToolCfgType; typedef enum { CFGASN_SOURCE = 0x0000000F, CFGASN_CMD = 0x00000001, CFGASN_CFG = 0x00000002, CFGASN_COUNT = 0x000000F0, CFGASN_ONCE = 0x00000010, CFGASN_TWICE = 0x00000020, CFGASN_MULTIPLE = 0x00000030, CFGASN_OPTIONAL = 0x00000100 } t_ToolCfgAssignment; #define CFGASSIGN_CMD ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_MULTIPLE )) #define CFGASSIGN_CFG_ONCE ((t_ToolCfgAssignment)(CFGASN_CFG | CFGASN_ONCE )) #define CFGASSIGN_CFG_MULTIPLE ((t_ToolCfgAssignment)(CFGASN_CFG | CFGASN_MULTIPLE )) #define CFGASSIGN_BOTH_ONCE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_ONCE )) #define CFGASSIGN_BOTH_TWICE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_TWICE )) #define CFGASSIGN_BOTH_MULTIPLE ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_MULTIPLE )) #define CFGASSIGN_OPTIONAL ((t_ToolCfgAssignment)(CFGASN_CMD | CFGASN_CFG | CFGASN_MULTIPLE | CFGASN_OPTIONAL)) typedef struct { t_pcchar pSetString; t_int SetValue; } t_ToolCfgSet, *t_pToolCfgSet; typedef struct { t_pcchar pName; /* The last one in the table must have pName set to NULL */ t_ToolCfgType CfgType; long DestAddr; /* For Params: the destination address: For table columns: the offset from the baseaddress */ t_int DestLen; /* for strings, this length DOES NOT include the trailing '\0' */ t_double MinValue; t_double MaxValue; t_pToolCfgSet pSetArray; } t_ToolCfgDataDesc, *t_pToolCfgDataDesc; /* ------------------------------------- */ /* Structure to describe one parameter */ /* ------------------------------------- */ typedef struct _t_ToolCfgParamDesc *t_pToolCfgParamDesc; typedef APIRET (* t_pToolCfgCallOnInitFn)(t_pToolCfgParamDesc pCfgParamDesc, t_pchar *ppErrorText); typedef struct _t_ToolCfgParamDesc { t_ToolCfgAssignment Assign; t_pToolCfgCallOnInitFn pCallOnInitFn; t_ToolCfgDataDesc DataDesc; /* The following two elements will be filled by the configuration scanner CfgScanConfiguration */ /* and do not need to be set by the calling function. */ t_int CmdAssignments; t_int CfgAssignments; } t_ToolCfgParamDesc; #define CFG_FILLUP_FORLINT 0,0 /* ------------------------------- */ /* Structure to describe a table */ /* ------------------------------- */ typedef APIRET (* t_pTableStartFn )(t_pchar pTableName, long *pBaseAddr, t_pcchar *ppErrorText); typedef APIRET (* t_pTableSaveAndNextFn)( long *pBaseAddr, t_pcchar *ppErrorText); typedef APIRET (* t_pTableEndFn )( t_pcchar *ppErrorText); typedef struct { t_pcchar pTableType; t_pTableStartFn pStartFn; t_pTableSaveAndNextFn pSaveAndNextFn; t_pTableEndFn pEndFn; t_pToolCfgDataDesc pDataDescArray; /* Pointer to array of data descriptors (one for each column) */ } t_ToolCfgTableDesc, *t_pToolCfgTableDesc; /* Prototype of the user's logfunction */ typedef void (* t_pToolCfgUserLogFn)(t_pcchar pFileName, t_pcchar pFunction, t_int LineNr, t_pcchar pFormat, va_list pArguments); /* ----------------- */ /* Prototypes */ /* ----------------- */ #ifdef __cplusplus #define EXTERN extern "C" #elif __STDC__ #define EXTERN extern #else #error Unknown C compiler mode #endif EXTERN APIRET ToolCfgInit (int argc, char *argv[]); EXTERN APIRET ToolCfgDeInit (void); EXTERN APIRET ToolCfgUseAdjustedCommandLine (int argc, char *argv[]); EXTERN APIRET ToolCfgSetLogFn (t_pToolCfgUserLogFn pUserLogFn); EXTERN APIRET ToolCfgGetCmdLineOption (t_pcchar pParamName, t_pcchar *ppValue); EXTERN APIRET ToolCfgAddGlobalSectionName (t_pcchar pSectionName); EXTERN APIRET ToolCfgDelGlobalSectionName (t_pcchar pSectionName); EXTERN APIRET ToolCfgScanConfiguration (t_pcchar pFileName, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray); EXTERN APIRET ToolCfgBuildTemplate (t_pcchar pFileName, t_pcchar pComment, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray); EXTERN APIRET ToolCfgLogConfiguration (t_pToolCfgParamDesc pParamDescArray); EXTERN APIRET ToolCfgPrintParamContents (t_pToolCfgParamDesc pParamDescArray, t_pchar pName, t_pchar pBuff); EXTERN APIRET ToolCfgGetSetString (t_pToolCfgSet pSetArray, int SetValue, const char **ppSetString); /* CfgGetCommandLineOption is usefull to the params that cannot be contained in the configuration file */ /* file itself, as for example the name of the cfg file. */ /* Use CfgScanConfiguration to read a certain section of the cfg file. The two arrays pParamDescArray */ /* and pTableDescArray specify the expected parameters and tables found in the indicated section. */ /* ------------------------------ */ /* Error codes */ /* ------------------------------ */ static const APIRET TOOLCFG_ERROR_OPEN_FAILED = ERROR_BASE_TOOL_CFG + 1; static const APIRET TOOLCFG_ERROR_READ_FAILED = ERROR_BASE_TOOL_CFG + 2; static const APIRET TOOLCFG_ERROR_CLOSE_FAILED = ERROR_BASE_TOOL_CFG + 3; static const APIRET TOOLCFG_ERROR_FILE_NOT_FOUND = ERROR_BASE_TOOL_CFG + 4; static const APIRET TOOLCFG_ERROR_SEEKEND_FAILED = ERROR_BASE_TOOL_CFG + 5; static const APIRET TOOLCFG_ERROR_SEEKSET_FAILED = ERROR_BASE_TOOL_CFG + 6; static const APIRET TOOLCFG_ERROR_INVALID_STATE = ERROR_BASE_TOOL_CFG + 7; static const APIRET TOOLCFG_ERROR_NAME_TOO_LONG = ERROR_BASE_TOOL_CFG + 8; static const APIRET TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW = ERROR_BASE_TOOL_CFG + 9; static const APIRET TOOLCFG_ERROR_CONFIG_ERROR = ERROR_BASE_TOOL_CFG + 10; static const APIRET TOOLCFG_ERROR_INVALID_ASSIGNMENT_OPTION = ERROR_BASE_TOOL_CFG + 11; static const APIRET TOOLCFG_ERROR_INVALID_CFGTYPE = ERROR_BASE_TOOL_CFG + 12; static const APIRET TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED = ERROR_BASE_TOOL_CFG + 13; static const APIRET TOOLCFG_ERROR_FPRINTF_FAILED = ERROR_BASE_TOOL_CFG + 14; static const APIRET TOOLCFG_ERROR_CMDLINE_OPTION_NOT_FOUND = ERROR_BASE_TOOL_CFG + 15; static const APIRET TOOLCFG_ERROR_SETBUF_FAILED = ERROR_BASE_TOOL_CFG + 16; static const APIRET TOOLCFG_ERROR_MALLOC_FAILED = ERROR_BASE_TOOL_CFG + 17; static const APIRET TOOLCFG_ERROR_SECTIONNAME_TOO_LONG = ERROR_BASE_TOOL_CFG + 18; static const APIRET TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES = ERROR_BASE_TOOL_CFG + 19; static const APIRET TOOLCFG_ERROR_SECTIONNAME_NOTFOUND = ERROR_BASE_TOOL_CFG + 20; static const APIRET TOOLCFG_ERROR_UNKNOWN_PARAMETER = ERROR_BASE_TOOL_CFG + 21; #endif libguytools2-2.0.5/include/toolconstants.h000066400000000000000000000073441322376377300207070ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Different useful constants // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLCONSTANTS_H__ #define __TOOLCONSTANTS_H__ /* --------------------------------------------------------------------------------------------- */ /* Attention */ /* This files only defines general, never-changing constants. Do not add application dependant */ /* definitions, such as string lengths, stack sizes etc. */ /* --------------------------------------------------------------------------------------------- */ /* ---------------- */ /* Time constants */ /* ---------------- */ #define MSEC_PER_SECOND 1000 #define USEC_PER_MSEC 1000 #define SECONDS_PER_DAY 86400 #define SECONDS_PER_HOUR 3600 #define SECONDS_PER_MINUTE 60 #define MSEC_PER_DAY (MS_PER_S * S_PER_DAY ) #define MSEC_PER_HOUR (MS_PER_S * S_PER_HOUR ) #define MSEC_PER_MINUTE (MS_PER_S * S_PER_MINUTE) #define DAYS_PER_WEEK 7 #define SECONDS_PER_WEEK (DAYS_PER_WEEK*SECONDS_PER_DAY) #define DAYS_PER_YEAR 365 // Attention, this is of #define SECONDS_PER_YEAR (SECONDS_PER_DAY * DAYS_PER_YEAR) // course just an estimation #define MONTHS_PER_YEAR 12 /* ---------------------- */ /* Weights and measures */ /* ---------------------- */ static const double LBS_PER_KG = 2.204623; static const double MM_PER_INCH = 25.4; #define UM_PER_M 1000000 #define UM_PER_MM 1000 #define MM_PER_M 1000 /* ---------------------- */ /* Mathematics */ /* ---------------------- */ static const double PI = 3.141592654; /* ---------------------- */ /* Computer stuff */ /* ---------------------- */ #define BYTES_PER_KILOBYTE 1024 #define BYTES_PER_MEGABYTE 1048576 #define CLIB_YEAROFFSET 1900 // Fixed year offset for struct tm (by ANSI) #define TCPIP_ADDRESS_LEN 15 // Address format: XXX.XXX.XXX.XXX -> 15 -- do not forget to add +1 if using C strings #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* ------------------ */ /* ASCII characters */ /* ------------------ */ static const char ASCII_ESC = 27; static const char ASCII_BS = 0x08; static const char ASCII_LF = 0x0A; static const char ASCII_CR = 0x0D; static const char ASCII_ENTER = ASCII_CR; static const char ASCII_EOF = 0x1A; #endif libguytools2-2.0.5/include/toolerror.h000066400000000000000000000107231322376377300200170ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Error handling // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLERROR_H__ #define __TOOLERROR_H__ #ifndef __FFL__ #define __FFL__ __FILE__, __FUNCTION__, __LINE__ #endif // ----------- // Constants // ----------- #define NO_ERROR 0 // --------------------------------------- // Macros for comfortable error checking // --------------------------------------- #define CHK(Func) \ /*lint -save -e506 -e774*/ /*Warning 506: Constant value Boolean; Info 774: Boolean within 'if' always evaluates to True */ \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ { \ (void)ToolErrorCheck (__FFL__, ec); \ return ec; \ } \ } \ /*lint -restore*/ #define CHK_CONST(ec) \ { \ (void)ToolErrorCheck (__FFL__, ec); \ return ec; \ } \ #define CHK_RET(Func) \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ return ec; \ } #define CHK_NORET(Func) \ { \ APIRET ec; \ if ((ec = Func) != NO_ERROR) \ (void)ToolErrorCheck (__FFL__, ec); \ } #define TOOL_CHK(Fn) \ { \ APIRET ec; \ if ((ec=Fn) != NO_ERROR) \ return ec; \ } // ------------------ // Type definitions // ------------------ typedef long APIRET; typedef long * pAPIRET; // ----------------------------- // ToolError's own error codes // ----------------------------- enum { TOOL_ERROR_ENTRY_NOT_FOUND = ERROR_BASE_TOOL_ERROR + 1, TOOL_ERROR_DUPLICATE_ENTRY , TOOL_ERROR_NOT_INITIALISED , TOOL_ERROR_ALREADY_INITIALISED }; // ------------------------------- // Prototypes and wrapper macros // ------------------------------- typedef void (* t_pToolErrorLogFn)(const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); APIRET ToolErrorSetLogFn (t_pToolErrorLogFn pLogFn); APIRET ToolErrorRegisterError (int ErrorCode, const char *pErrorMsg); APIRET ToolErrorGetMessage (int ErrorCode, const char **ppMessage); const char *ToolErrorMessage (int ErrorCode); const char *ToolErrorTranslateErrno (int Errno); APIRET ToolErrorInit (int MaxErrors); APIRET ToolErrorDeInit (void); APIRET ToolErrorCheck (char const *pFileName, char const *pFunctionName, int LineNr, int ErrorCode); APIRET ToolErrorLog (char const *pFileName, char const *pFunctionName, int LineNr, const char * pFormat, ...) __attribute__ ((format (printf, 4, 5))); #define TOOL_ERROR_REGISTER_CODE(ErrorCode) ToolErrorRegisterError(ErrorCode, #ErrorCode) #endif libguytools2-2.0.5/include/toolglobalid.h000066400000000000000000000064141322376377300204450ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Unique IDs for tools and applications // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLGLOBALID_H__ #define __TOOLGLOBALID_H__ /* ------------------------------- */ /* Constants */ /* ------------------------------- */ /* ------------------------------- */ /* Base id's */ /* ------------------------------- */ const unsigned int ID_BASE = 0; const unsigned int ID_OFFSET_PROJECT =10000000; /* 100 projects */ const unsigned int ID_OFFSET_SUBPROJECT = 100000; /* 100 subprojects */ const unsigned int ID_OFFSET_SUBSUBPROJECT = 1000; /* 1st possibility -- 100 subsubprojects (=100 C-files with max. 1000 IDs) */ const unsigned int ID_OFFSET_SUBSUBSUBPROJECT = 100; /* 2nd possibility -- 100 subsubprojects (=100 subdir's) */ /* each of the 100 subsubprojects has max. 10 subsubsubprojects (=10 C-files with max. 100 IDs) */ #define CREATE_BASE_ID(ProjectName, x) \ const unsigned int ID_BASE_ ## ProjectName = x; #define CREATE_IDS(ModulName, x) \ const unsigned int ERROR_BASE_ ## ModulName = x; \ const unsigned int MEMID_BASE_ ## ModulName = x; /* ========================== TOOLS ================================ */ CREATE_BASE_ID (TOOLS, ID_BASE + 0*ID_OFFSET_PROJECT) CREATE_IDS (TOOL_CFG , ID_BASE_TOOLS + 0*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_ERROR , ID_BASE_TOOLS + 1*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_LOG , ID_BASE_TOOLS + 2*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_SIGNAL , ID_BASE_TOOLS + 3*ID_OFFSET_SUBPROJECT) CREATE_IDS (TOOL_SYSINFO , ID_BASE_TOOLS + 4*ID_OFFSET_SUBPROJECT) /* ========================= GUYMAGER ============================== */ CREATE_BASE_ID (GUYMAGER, ID_BASE + 1*ID_OFFSET_PROJECT) CREATE_IDS (GUYMAGER_MAIN , ID_BASE_GUYMAGER + 0*ID_OFFSET_SUBPROJECT) #endif libguytools2-2.0.5/include/toollog.h000066400000000000000000000056271322376377300174560ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Log utility // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __LOG_H__ #define __LOG_H__ class t_Log { public: typedef enum { Debug=0, Info, Error, Entries // must always be the last element in the list } t_Level; t_Log (const char* pFileName, APIRET &rc); ~t_Log (void); static bool IsInitialised (void); static void GetLibGuyToolsVersion (const char **pVersion); static void vEntry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void Entry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) __attribute__ ((format (printf, 5, 6))); static void vEntryDebug (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void vEntryInfo (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); static void vEntryError (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments); #define LOG_DEBUG(...) t_Log::Entry (t_Log::Debug, __FFL__, __VA_ARGS__); #define LOG_INFO(...) t_Log::Entry (t_Log::Info , __FFL__, __VA_ARGS__); #define LOG_ERROR(...) t_Log::Entry (t_Log::Error, __FFL__, __VA_ARGS__); // Possible error codes // -------------------- static const APIRET TOOLLOG_ERROR_INITIALISED_TWICE = ERROR_BASE_TOOL_LOG + 1; static const APIRET TOOLLOG_ERROR_HOSTNAME_TOO_LONG = ERROR_BASE_TOOL_LOG + 2; }; #endif libguytools2-2.0.5/include/toolsignal.h000066400000000000000000000065111322376377300201430ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Signal handler with backtrace // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLSIGNAL_H__ #define __TOOLSIGNAL_H__ // Description of module ToolSignal // -------------------------------- // This module does all the standard signal handling work for an application. When catching a standard // signal (Kill, Hup, Break...) it calls the function that has been indicated in param pFnLog. // If ever a segment violation occurs, a stack trace is done in order to log the function call sequence // before exiting the program. // // All logging is done via the function indicated in param pFnLog. If that one is NULL, the module writes // its log outputs to stdout. Its first parameter (Error) indicates whether a normal log output (info) or // whether an error log entry should be done. // // It might be important to know for the application, that ToolSignalInit starts a new thread. The function // indicated in param pFnSig is called from that thread, if pFnSig is not NULL. The ID of the new thread is // written to where pThreadId points, if pThreadId is not NULL. typedef void (* t_pToolSignalLogFn )(bool Error, int ThreadNr, const char *pFileName, const char *pFunction, int LineNr, const char *pFormat, va_list pArguments); typedef void (* t_pToolSignalHandler)(int Signal); int ToolSignalInit (t_pToolSignalLogFn pFnLog, t_pToolSignalHandler pFnSig, int *pThreadId); int ToolSignalDeInit (void); // class t_ToolSignal: public QThread // { // public: // t_ToolSignal (int Err, int *pThreadId); // ~t_ToolSignal(); // void run(); // static void BacktraceSignalHandler (int signalHandled, siginfo_t *signalInfo, void *secret); // // static APIRET SetLogFn (t_pToolSignalLogFn pFn); // static APIRET SetSignalHandlerFn (t_pToolSignalHandler pFn); // }; // typedef t_ToolSignal *t_pToolSignal; // ------------------------------- // Error codes // ------------------------------- enum { ERROR_TOOLSIGNAL_ALREADY_INITIALISED = ERROR_BASE_TOOL_SIGNAL + 1, ERROR_TOOLSIGNAL_NOT_INITIALISED, ERROR_TOOLSIGNAL_STARTTHREAD_FAILED }; #endif libguytools2-2.0.5/include/toolsysinfo.h000066400000000000000000000044151322376377300203610ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: System information // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLSYSINFO_H__ #define __TOOLSYSINFO_H__ // ------------------------------ // Constants and Structures // ------------------------------ const int TOOLSYSINFO_MACADDRLEN_VAL = 6; const int TOOLSYSINFO_MACADDRLEN_STR = 2*TOOLSYSINFO_MACADDRLEN_VAL; typedef struct { unsigned char AddrVal [TOOLSYSINFO_MACADDRLEN_VAL ]; char AddrStr [TOOLSYSINFO_MACADDRLEN_STR+1]; } t_ToolSysInfoMacAddr, *t_pToolSysInfoMacAddr; // ------------------------------ // Functions // ------------------------------ APIRET ToolSysInfoGetMacAddr (t_pToolSysInfoMacAddr pMacAddr); APIRET ToolSysInfoUname (QString &Uname); APIRET ToolSysInfoInit (void); APIRET ToolSysInfoDeInit (void); // ------------------------------ // Error codes // ------------------------------ enum { TOOLSYSINFO_ALREADY_INITIALISED = ERROR_BASE_TOOL_SYSINFO + 1, TOOLSYSINFO_ERROR_SOCKET, TOOLSYSINFO_ERROR_NO_ADDR, TOOLSYSINFO_ERROR_UNAME }; #endif libguytools2-2.0.5/include/tooltarget.h000066400000000000000000000003711322376377300201520ustar00rootroot00000000000000/* ------------------------------------------------------------------ */ /* This file specifies the target compilation for the whole TOOLBOX */ /* ------------------------------------------------------------------ */ #define TOOL_MAX_THREADS 500 libguytools2-2.0.5/include/tooltypes.h000066400000000000000000000044001322376377300200250ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Type definitions // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef __TOOLTYPES_H__ #define __TOOLTYPES_H__ #ifndef NO_ERROR #define NO_ERROR 0 #endif // Remember, char, signed char and unsigned char are 3 different types // as stated by ANSI-C, but there are only two representations !!! typedef char t_char; typedef char * t_pchar; typedef const char * t_pcchar; typedef signed char t_schar; typedef signed char * t_pschar; typedef unsigned char t_uchar; typedef unsigned char * t_puchar; typedef short t_short; typedef short * t_pshort; typedef unsigned short t_ushort; typedef unsigned short * t_pushort; typedef int t_int; typedef int * t_pint; typedef unsigned int t_uint; typedef unsigned int * t_puint; typedef void t_void; typedef void * t_pvoid; typedef float t_float; typedef float * t_pfloat; typedef double t_double; typedef double * t_pdouble; #endif libguytools2-2.0.5/toolcfg.cpp000066400000000000000000002573501322376377300163460ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Configuration utility // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . /* ------------------------------ */ /* Includes */ /* ------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include "tooltypes.h" #include "toolglobalid.h" #include "toolconstants.h" #include "toolerror.h" #include "toolcfg.h" /* ------------------------------ */ /* Constants */ /* ------------------------------ */ const t_char CHAR_LF = 0x0A; const t_char CHAR_CR = 0x0D; const t_char CHAR_EOF = 0x1A; const t_char CHAR_APPEND_LINE = '\\'; const t_char STRING_DELIMITER = '\''; const t_int MAX_CFG_NESTING_LEVEL = 6; /* maximum number of nested INCLUDE directives */ /* reserved keywords */ static t_pcchar KEYWORD_TABLESTART = "TABLE"; static t_pcchar KEYWORD_TABLEEND = "ENDTABLE"; static t_pcchar KEYWORD_SECTIONSTART = "SECTION"; static t_pcchar KEYWORD_SECTIONEND = "ENDSECTION"; static t_pcchar KEYWORD_INCLUDE = "INCLUDE"; static t_pcchar KEYWORD_INCLUDE_OPT = "INCLUDE_OPTIONAL"; static t_pcchar KEYWORD_REMARK = "REM"; static t_pcchar KEYWORD_DEFINE = "DEFINE"; static t_pcchar KEYWORD_UNDEFINE = "UNDEFINE"; // static t_pcchar MINUS_LINE = "------------------------------------------------------------------------------" // "------------------------------------------------------------------------------" // "------------------------------------------------------------------------------"; /* ------------ */ /* Memory IDs */ /* ------------ */ static const t_int MemIdCfgBuffer = MEMID_BASE_TOOL_CFG + 0; static const t_int MemIdCfgErrorHeader = MEMID_BASE_TOOL_CFG + 1; static const t_int MemIdCfgContextStack = MEMID_BASE_TOOL_CFG + 2; static const t_int MemIdCfgTemplateHeader = MEMID_BASE_TOOL_CFG + 3; static const t_int MemIdCfgHelpBuff = MEMID_BASE_TOOL_CFG + 4; static const t_int MemIdCfgHelpString = MEMID_BASE_TOOL_CFG + 5; static const t_int MemIdCfgHelpInt = MEMID_BASE_TOOL_CFG + 6; static const t_int MemIdCfgHelpTable = MEMID_BASE_TOOL_CFG + 7; static const t_int MemIdCfgTableType = MEMID_BASE_TOOL_CFG + 8; static const t_int MemIdCfgTableName = MEMID_BASE_TOOL_CFG + 9; static const t_int MemIdCfgLogConfiguration = MEMID_BASE_TOOL_CFG + 10; /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef enum { /*! \brief Command line parameter priority */ PRIORITY_HIGH, /*!< Command line parameters have high priority */ PRIORITY_LOW /*!< Command line parameters have low priority */ } t_Priority; typedef enum /*! \brief States for CFG parser state machine */ { CFGSTATE_INCLUDENEWFILE, CFGSTATE_INCLUDENEWFILE_OPT, CFGSTATE_GETNEWLINE, CFGSTATE_CHECKINCLUDE, CFGSTATE_CHECKSECTION, CFGSTATE_LINEREAD, CFGSTATE_COMPLETED, CFGSTATE_CHECKEOF, CFGSTATE_SEARCHSECTIONEND, CFGSTATE_CHECKSECTIONEND } t_ToolCfgState; #define MAX_SECTIONNAME_LEN 63 #define MAX_FILENAME_LEN 4095 #define MAX_SECTIONNAMES 16 #define MAX_GLOBALSECTIONNAMES 16 typedef char t_ToolCfgSectionName[MAX_SECTIONNAME_LEN+1]; typedef struct { t_int BufferLen; t_int ActLineLen; t_int ActLineNr; t_pchar pActLine; t_pchar pBuffer; t_char FileName [MAX_FILENAME_LEN +1]; t_ToolCfgSectionName SectionNameArr[MAX_SECTIONNAMES]; // These section names are only valid during the the scanning of one include file t_int SectionNesting; t_ToolCfgState State; } t_ToolCfgContext, *t_pToolCfgContext; typedef struct { int argc; char **argv; t_Priority Priority; t_pToolCfgUserLogFn pUserLogFn; t_pToolCfgContext pCfgContextStack; t_pToolCfgContext pActCfgContext; t_int IncludeNestingLevel; t_int MaxIncludeNestingLevel; t_char TempFileName[MAX_FILENAME_LEN+1]; t_ToolCfgSectionName GlobalSectionNameArr[MAX_GLOBALSECTIONNAMES]; // These section names remain defined during the whole cfg sanning time } t_ToolCfgLocal; #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) /* ------------------------------ */ /* Variables */ /* ------------------------------ */ t_ToolCfgLocal ToolCfgLocal; /* ------------------------------ */ /* Functions */ /* ------------------------------ */ /* -------------------------------------- */ /* Memory access with / without ToolMem */ /* -------------------------------------- */ #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX #define MEM_OPT_NONE 0 #define MEM_REGISTER_MEMID(MemId) NO_ERROR #endif static APIRET ToolCfgMemAlloc (t_pvoid *ppMem, t_uint Size, t_uint Options, t_int MemId) { APIRET rc; #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX rc = Options; // To prevent from compiler warning "unused..." rc = MemId; // To prevent from compiler warning "unused..." *ppMem = malloc (Size); if (*ppMem == NULL) rc = TOOLCFG_ERROR_MALLOC_FAILED; else rc = NO_ERROR; #else rc = ToolMemAlloc (ppMem, Size, Options, MemId); #endif return rc; } static APIRET ToolCfgMemFree (t_pvoid pMem, t_int MemId) { APIRET rc; #ifdef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX rc = MemId; // To prevent from compiler warning "unused..." free (pMem); rc = NO_ERROR; #else rc = ToolMemFree (pMem, MemId); #endif return rc; } /* -------------------- */ /* Error management */ /* -------------------- */ /* Error return values in this module are simply raised to the calling function. */ /* This way, the module CFG does not depend on any log management. */ #define CFG_CHK_APP(Fn) \ { \ APIRET ec; \ \ if ((ec=Fn) != NO_ERROR) \ { \ if (ec != TOOLCFG_ERROR_CONFIG_ERROR) \ (void) ToolCfgLogEntry(__FFL__, "Error %d.", ec); \ return ec; \ } \ } #define CFG_CHK_FPRINTF(Fn) \ { \ if ((Fn) < 1) \ return TOOLCFG_ERROR_FPRINTF_FAILED; \ } static APIRET ToolCfgLogEntry (t_pcchar pFileName, t_pcchar pFunctionName, t_int LineNr, t_pcchar pFormat, ...) { // APIRET rc=1; va_list VaList; va_start(VaList, pFormat); /* VaList points to the argument following pFormat */ if (ToolCfgLocal.pUserLogFn) (*ToolCfgLocal.pUserLogFn)(pFileName, pFunctionName, LineNr, pFormat, VaList); // if (rc) // (void) vfprintf (stderr, pFormat, VaList); va_end(VaList); return NO_ERROR; } static APIRET ToolCfgStdErrorHeader (t_pcchar pActCursor) { t_pToolCfgContext pCfgContext; t_pchar pEndOfLine; t_pchar pBuff; t_int Cursor; t_int LineLen; pCfgContext = ToolCfgLocal.pActCfgContext; if (pCfgContext->FileName[0] == '\0') CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error in command line. Parameter %d", pCfgContext->ActLineNr)) else CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error in file %s line %d" , &pCfgContext->FileName[0], pCfgContext->ActLineNr)) if (pCfgContext->pActLine) { pEndOfLine = pCfgContext->pActLine + pCfgContext->ActLineLen; *pEndOfLine = '\0'; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "[%s]", pCfgContext->pActLine)) } if (pActCursor && pCfgContext->pActLine) { LineLen = (t_int) strlen (pCfgContext->pActLine); Cursor = pActCursor - pCfgContext->pActLine; Cursor = max (Cursor, 0 ); Cursor = min (Cursor, LineLen-1); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pBuff, (t_uint)(LineLen+3), MEM_OPT_NONE, MemIdCfgErrorHeader)) /* +3 for [ ] and '\0' */ (void) sprintf (pBuff, "[%*s^%*s]", Cursor, "", LineLen-Cursor-1, ""); CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pBuff)) CFG_CHK_APP (ToolCfgMemFree (pBuff, MemIdCfgErrorHeader)) } return NO_ERROR; } /* ------------------------------------- */ /* Utility functions */ /* ------------------------------------- */ static t_int ToolCfgStrCmpNoCase (const char *pStr1, const char *pStr2) { #ifdef _WIN32 return strcmpi (pStr1, pStr2); #else return strcasecmp (pStr1, pStr2); #endif } static t_int ToolCfgStrNCmpNoCase (const char *pStr1, const char *pStr2, t_int Len) { #ifdef _WIN32 return strnicmp (pStr1, pStr2, Len); #else return strncasecmp (pStr1, pStr2, (size_t)Len); #endif } static t_pchar ToolCfgStrMaxCpy (t_pchar pDest, t_pcchar pSrc, t_int DestLen) { if (DestLen == 0) return pDest; pDest[DestLen-1] = '\0'; return strncpy (pDest, pSrc, DestLen-1); } static APIRET ToolCfgCopyName (t_pcchar pSrc, t_pchar pDst, t_int DstLen) { t_int SrcLen; if (pSrc == NULL) pDst[0] = '\0'; else { SrcLen = (t_int)strlen(pSrc); if (SrcLen > DstLen) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SrcLen: %d DstLen: %d", SrcLen, DstLen)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SrcString: %50.50s", pSrc)) return TOOLCFG_ERROR_NAME_TOO_LONG; } else (void) strcpy (pDst, pSrc); } return NO_ERROR; } static APIRET ToolCfgFindFirstWord (t_pcchar pActLine, const char **ppFirstWord, t_int LineLen, t_pint pRemLineLen) { for ( *ppFirstWord = pActLine; ((**ppFirstWord == ' ') || (**ppFirstWord == '\t')) && (LineLen > 0); ( *ppFirstWord)++, LineLen--) { } if ((LineLen <= 0) || (**ppFirstWord == CHAR_LF) || (**ppFirstWord == CHAR_CR)) *ppFirstWord = NULL; *pRemLineLen = LineLen; return NO_ERROR; } static APIRET ToolCfgCompareKeyWord (t_pcchar pTableKeyWord, t_pchar pCheckKeyWord, t_int LineLen, t_pint pEq, t_pchar *ppNextChar) { t_pchar pNextChar; t_int TableKeyLen; t_int CheckKeyLen; t_pchar pCh; pNextChar = NULL; *pEq = FALSE; TableKeyLen = (t_int) strlen (pTableKeyWord); if (pCheckKeyWord && (LineLen >= TableKeyLen)) { CheckKeyLen = 0; for (pCh = pCheckKeyWord; (*pCh != ' ') && (*pCh != CHAR_CR) && (*pCh != '=') && (*pCh != CHAR_LF) && (*pCh != '\t') && (*pCh != '\0'); pCh++) CheckKeyLen++; if (CheckKeyLen == TableKeyLen) { if (ToolCfgStrNCmpNoCase (pTableKeyWord, pCheckKeyWord, CheckKeyLen) == 0) { pNextChar = &pCheckKeyWord[CheckKeyLen]; *pEq = TRUE; } } } if (ppNextChar) *ppNextChar = pNextChar; return NO_ERROR; } static APIRET ToolCfgGetParamLen (t_pcchar pParam, t_pint pParamLen) { t_int LoopEnd; /* count param len */ *pParamLen = 0; LoopEnd = FALSE; if (*pParam == STRING_DELIMITER) { pParam++; (*pParamLen)++; while (!LoopEnd) { if (*pParam == '\0') LoopEnd = TRUE; else if (*pParam == STRING_DELIMITER) { if (*(pParam+1) == STRING_DELIMITER) { pParam++; (*pParamLen)++; } else { LoopEnd = TRUE; } } if (!LoopEnd) { pParam++; (*pParamLen)++; } } } else { while ((*pParam != ' ') && (*pParam != '\t') && (*pParam != '\0') && (*pParam != CHAR_CR) && (*pParam != CHAR_LF)) { pParam++; (*pParamLen)++; } } if (*pParam == STRING_DELIMITER) /* is there a string end delimiter? */ { pParam++; (*pParamLen)++; } /* was there a param? */ // if ((*pParam == '\0') && (*pParamLen == 0)) if (*pParamLen == 0) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgCheckIfOnlyOneParam (t_pchar pParam, t_pint pParamLen) { CFG_CHK_APP (ToolCfgGetParamLen (pParam, pParamLen)) pParam += *pParamLen; /* skip trailing spaces */ while (((*pParam == ' ') || (*pParam == '\t')) && (*pParam != '\0')) pParam++; /* is there a second param? */ if (*pParam != '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgCheckIfNoParam (t_pchar pCh) { while (((*pCh == ' ') || (*pCh == '\t')) && (*pCh != '\0')) pCh++; if (*pCh != '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader (pCh)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } /* ----------------------------------------------------------------------------------- */ /* Help text builder. It is used to help the user enter the correct parameter values */ /* ----------------------------------------------------------------------------------- */ static APIRET ToolCfgChkStrCpy (t_pchar pDstStr, t_pcchar pSrcStr, t_pint pCumulLen) { if (pDstStr) (void) strcpy (pDstStr + *pCumulLen, pSrcStr); (*pCumulLen) += (t_int)strlen (pSrcStr); return NO_ERROR; } static APIRET ToolCfgBuildHelpHMS(t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; t_int MinVal; t_int MaxVal; MinVal = (t_int)pCfgDataDesc->MinValue; MaxVal = (t_int)pCfgDataDesc->MaxValue; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%02d:%02d:%02d..%02d:%02d:%02d]", MinVal/3600, (MinVal/60)%60, MinVal%60, MaxVal/3600, (MaxVal/60)%60, MaxVal%60); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpPresence (t_pToolCfgDataDesc /*pCfgDataDesc*/, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pcchar pTmp; pTmp = "Optional"; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) return NO_ERROR; } static APIRET ToolCfgBuildHelpInteger (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%d..%d] | [0x%X..0x%X]", (t_int)pCfgDataDesc->MinValue, (t_int)pCfgDataDesc->MaxValue, (t_int)pCfgDataDesc->MinValue, (t_int)pCfgDataDesc->MaxValue); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpDouble (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpInt)) (void) sprintf (pTmp, "[%G..%G]", pCfgDataDesc->MinValue, pCfgDataDesc->MaxValue); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpInt)) return NO_ERROR; } static APIRET ToolCfgBuildHelpString (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pchar pTmp; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 256, MEM_OPT_NONE, MemIdCfgHelpString)) (void) sprintf (pTmp, "''", (t_int)pCfgDataDesc->DestLen); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pTmp, pHelpBuffLen)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpString)) return NO_ERROR; } static APIRET ToolCfgBuildHelpSet (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { t_pToolCfgSet pSetArray; t_int i; pSetArray = pCfgDataDesc->pSetArray; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, "[", pHelpBuffLen)) for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) /* end of array? */ break; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pSetArray[i].pSetString, pHelpBuffLen)) if (pSetArray[i+1].pSetString) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, ", ", pHelpBuffLen)) } CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, "]", pHelpBuffLen)) return NO_ERROR; } static APIRET ToolCfgBuildHelpRange (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { switch (pCfgDataDesc->CfgType) { case CFGTYPE_PRESENCE: CFG_CHK_APP (ToolCfgBuildHelpPresence (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_INTEGER: CFG_CHK_APP (ToolCfgBuildHelpInteger (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_DOUBLE: CFG_CHK_APP (ToolCfgBuildHelpDouble (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_STRING: CFG_CHK_APP (ToolCfgBuildHelpString (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_SET: CFG_CHK_APP (ToolCfgBuildHelpSet (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_HMS: CFG_CHK_APP (ToolCfgBuildHelpHMS (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) break; case CFGTYPE_NULL: break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } return NO_ERROR; } static APIRET ToolCfgBuildHelp (t_pToolCfgDataDesc pCfgDataDesc, t_pchar pHelpBuff, t_pint pHelpBuffLen) { *pHelpBuffLen = 0; CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, pCfgDataDesc->pName, pHelpBuffLen)) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff, " = " , pHelpBuffLen)) CFG_CHK_APP (ToolCfgBuildHelpRange (pCfgDataDesc, pHelpBuff, pHelpBuffLen)) (*pHelpBuffLen)++; return NO_ERROR; } static APIRET ToolCfgBuildTableHelp (t_pToolCfgTableDesc pCfgTableDesc, t_pchar pHelpBuff1, t_pchar pHelpBuff2, t_pint pHelpBuffLen) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pTmp; t_int i; t_int NameLen; t_int RangeLen; t_int Spaces; t_int HelpBuffLenDummy; t_int PrevLen; *pHelpBuffLen = 0; HelpBuffLenDummy = 0; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, 4096, MEM_OPT_NONE, MemIdCfgHelpTable)) for (i=0;;i++) { pCfgDataDesc = &pCfgTableDesc->pDataDescArray[i]; if (pCfgDataDesc->pName == NULL) break; NameLen = (t_int)strlen (pCfgDataDesc->pName); CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, pCfgDataDesc->pName, pHelpBuffLen)) PrevLen = HelpBuffLenDummy; CFG_CHK_APP (ToolCfgBuildHelpRange (pCfgDataDesc, pHelpBuff2, &HelpBuffLenDummy)) RangeLen = HelpBuffLenDummy - PrevLen; if (RangeLen != NameLen) { Spaces = abs (RangeLen - NameLen); memset (pTmp, ' ', Spaces); pTmp[Spaces] = '\0'; if (RangeLen > NameLen) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, pTmp, pHelpBuffLen )) else CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff2, pTmp, &HelpBuffLenDummy)) } CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff1, " ", pHelpBuffLen )) CFG_CHK_APP (ToolCfgChkStrCpy (pHelpBuff2, " ", &HelpBuffLenDummy)) } CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpTable)) (*pHelpBuffLen)++; return NO_ERROR; } static APIRET ToolCfgQueryFileInfo (t_pchar pFileName, t_pint pYear, t_pint pMonth , t_pint pDay, t_pint pHour, t_pint pMinute, t_pint pSize) { // OS/2 code // --------- // FILEFINDBUF3 FindBuff; // HDIR hDir; // ULONG Count; // // hDir = HDIR_SYSTEM; // Count = 1; // Search for only 1 entry // CFG_CHK_APP(DosFindFirst(pFileName, &hDir, FILE_NORMAL, &FindBuff, sizeof(FILEFINDBUF3), &Count, FIL_STANDARD)) // CFG_CHK_APP(DosFindClose(hDir)) // // if (pYear ) *pYear = FindBuff.fdateLastWrite.year + OS2DOS_YEAROFFSET; // if (pMonth ) *pMonth = FindBuff.fdateLastWrite.month; // if (pDay ) *pDay = FindBuff.fdateLastWrite.day; // if (pHour ) *pHour = FindBuff.ftimeLastWrite.hours; // if (pMinute) *pMinute = FindBuff.ftimeLastWrite.minutes; // if (pSize ) *pSize = (t_int)FindBuff.cbFile; // Linux code // ---------- struct stat FileInfo; struct tm* LastModified = NULL; memset (&FileInfo, 0, sizeof(FileInfo)); // Get file statistics if (((stat (pFileName, &FileInfo)) == -1) || (!(FileInfo.st_mode & S_IFREG))) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Could not stat configuration file %s: file not found", pFileName)) return TOOLCFG_ERROR_FILE_NOT_FOUND; } LastModified = localtime (&(FileInfo.st_mtime)); if (pYear ) *pYear = LastModified->tm_year + 1900; if (pMonth ) *pMonth = LastModified->tm_mon + 1; if (pDay ) *pDay = LastModified->tm_mday; if (pHour ) *pHour = LastModified->tm_hour; if (pMinute) *pMinute = LastModified->tm_min; if (pSize ) *pSize = FileInfo.st_size; return NO_ERROR; } static APIRET ToolCfgReadCmdLine (t_pToolCfgContext pCfgContext) { t_pchar pTmp; t_int i; t_uint Alloc; t_int SpaceSplit; /* Find size */ pCfgContext->BufferLen = 0; for (i=1; iBufferLen += (t_int) strlen (ToolCfgLocal.argv[i]) + 1; /* +1 for CR */ } pCfgContext->BufferLen++; /* ++ for ending '\0' */ /* Alloc memory */ Alloc = pCfgContext->BufferLen; if (Alloc == sizeof(t_pvoid)) Alloc++; CFG_CHK_APP (ToolCfgMemAlloc((void **)&pCfgContext->pBuffer, Alloc, MEM_OPT_NONE, MemIdCfgBuffer)) // Read command line into buffer, seperate arguments by a spaces pTmp = pCfgContext->pBuffer; for (i=1; ipBuffer; *pTmp != '\0'; pTmp++) { if (*pTmp == STRING_DELIMITER) SpaceSplit = !SpaceSplit; if (SpaceSplit && (*pTmp == ' ')) *pTmp = CHAR_CR; } // pTmp = pCfgContext->pBuffer; // for (i=1; iActLineLen = 0; pCfgContext->ActLineNr = 1; pCfgContext->pActLine = pCfgContext->pBuffer; return NO_ERROR; } static APIRET ToolCfgReadCfgFile (t_pToolCfgContext pCfgContext) { FILE *pCfgFile; t_int SizeRead; t_int rc; t_int Year, Month , Day; t_int Hour, Minute; t_int Size; /* Expand filename (only possible when using the toolbox) */ #ifndef TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX (void) strcpy (&ToolCfgLocal.TempFileName[0], &pCfgContext->FileName[0]); CFG_CHK_APP (ToolEnvExpand (&ToolCfgLocal.TempFileName[0], &pCfgContext->FileName[0], MAX_FILENAME_LEN)) #endif /* Find size */ pCfgFile = fopen (&pCfgContext->FileName[0], "rb"); if (pCfgFile == NULL) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Could not open configuration file %s", &pCfgContext->FileName[0])) return TOOLCFG_ERROR_OPEN_FAILED; } rc = setvbuf (pCfgFile, NULL, _IOFBF, 32768); if (rc) return TOOLCFG_ERROR_SETBUF_FAILED; rc = fseek (pCfgFile, 0, SEEK_END); if (rc) return TOOLCFG_ERROR_SEEKEND_FAILED; pCfgContext->BufferLen = (t_int) ftell (pCfgFile) + 1; /* +1 for ending '\0' */ /* Alloc memory */ CFG_CHK_APP (ToolCfgMemAlloc((void **)&pCfgContext->pBuffer, (t_uint)pCfgContext->BufferLen, MEM_OPT_NONE, MemIdCfgBuffer)) /* Read command line into buffer */ rc = fseek (pCfgFile, 0, SEEK_SET); if (rc) return TOOLCFG_ERROR_SEEKSET_FAILED; SizeRead = (t_int) fread (pCfgContext->pBuffer, 1, (size_t)pCfgContext->BufferLen, pCfgFile); if (SizeRead > pCfgContext->BufferLen) return TOOLCFG_ERROR_READ_FAILED; rc = fclose (pCfgFile); if (rc) return TOOLCFG_ERROR_CLOSE_FAILED; pCfgContext->pBuffer[SizeRead] = '\0'; CFG_CHK_APP (ToolCfgQueryFileInfo (&pCfgContext->FileName[0], &Year, &Month, &Day, &Hour, &Minute, &Size)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Scanning configuration file %s (%d bytes %02d.%02d.%d %02d:%02d)", &pCfgContext->FileName[0], Size, Day, Month, Year, Hour, Minute)) /* Set initial context */ pCfgContext->ActLineLen = 0; pCfgContext->ActLineNr = 1; pCfgContext->pActLine = pCfgContext->pBuffer; return NO_ERROR; } static APIRET ToolCfgGetLineLen (t_pToolCfgContext pCfgContext) { t_pchar pEol; t_pchar pLastBackslash; t_int CopyLen; t_int KeepRunning; pLastBackslash = NULL; KeepRunning = TRUE; pEol = pCfgContext->pActLine; while (KeepRunning) { switch (*pEol) { case CHAR_APPEND_LINE: pLastBackslash = pEol++; break; case ' ' : case '\t' : pEol++; break; case CHAR_CR: case CHAR_LF: if (pLastBackslash) { if (((*pEol == CHAR_CR) && (pEol[1] == CHAR_LF)) || ((*pEol == CHAR_LF) && (pEol[1] == CHAR_CR))) pEol++; pEol++; CopyLen = pCfgContext->pBuffer + pCfgContext->BufferLen - pEol; memmove (pLastBackslash, pEol, CopyLen); pEol = pLastBackslash; pLastBackslash = NULL; pCfgContext->ActLineNr++; } else KeepRunning = FALSE; break; case '\0' : KeepRunning = FALSE; break; default : pLastBackslash = NULL; pEol++; } } pCfgContext->ActLineLen = pEol - pCfgContext->pActLine; return NO_ERROR; } static APIRET ToolCfgSearchLine (t_pToolCfgContext pCfgContext) { t_pchar pTmp; pTmp = pCfgContext->pActLine + pCfgContext->ActLineLen; if (*pTmp != '\0') { if (((pTmp[0] == CHAR_LF) && (pTmp[1] == CHAR_CR)) || ((pTmp[1] == CHAR_LF) && (pTmp[0] == CHAR_CR))) pTmp += 2; else pTmp += 1; } pCfgContext->ActLineNr++; pCfgContext->pActLine = pTmp; CFG_CHK_APP (ToolCfgGetLineLen (pCfgContext)) return NO_ERROR; } /* CfgNoFurtherParamsExpected reports an error if further */ /* parameters are found between pStart and the end of line. */ static APIRET ToolCfgNoFurtherParamsExpected (t_pcchar pStart, t_pcchar pCorrectSyntaxText) { while ((*pStart == ' ') || (*pStart == '\t')) pStart++; if ((*pStart != CHAR_CR) && (*pStart != CHAR_LF) && (*pStart != '\0')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pStart)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No further parameter expected.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pCorrectSyntaxText)) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } //static t_pchar ToolCfgFindEndOfString (t_pchar pString) //{ // t_pchar pTmp; // // for ( pTmp = pString; // (*pTmp != CHAR_CR) && (*pTmp != ' ') && // (*pTmp != CHAR_LF) && (*pTmp != '\t') && (*pTmp != '\0'); // pTmp++) // { // } // return pTmp-1; //} static t_int ToolCfgScanningCmdLine (void) { if (ToolCfgLocal.pActCfgContext->FileName[0] == '\0') return TRUE; else return FALSE; } static APIRET ToolCfgDropContext (t_pToolCfgContext pCfgContext) { CFG_CHK_APP (ToolCfgMemFree (pCfgContext->pBuffer, MemIdCfgBuffer)) return NO_ERROR; } /* CfgGetNextLine is the core function of the configuration scanner. From the calling */ /* function's point of view, it simply reads the next line (or returns ppLine = NULL if */ /* no more data can be found). Internally it manages the INCLUDE and SECTION statements */ /* as well as trailing backslashes (for joining lines). */ static APIRET ToolCfgGetNextLine (t_pchar *ppLine, t_pint pLineLen) { t_pToolCfgContext pContext; t_pchar pEol, pTmp, pKeyWord, pFirstWord; t_int ParamLen; t_int RemLineLen; char TmpChar; t_int KeyLen; t_int KeyLenSectionStart; t_int KeyLenSectionEnd; t_int SectionNameFound; t_int i; t_int SectionSubNesting; bool ChkInclude; bool ChkIncludeOpt; APIRET rc; char Space[] = " "; pTmp = Space; pContext = ToolCfgLocal.pActCfgContext; while ((pContext->State != CFGSTATE_LINEREAD) && (pContext->State != CFGSTATE_COMPLETED)) { switch (pContext->State) { case CFGSTATE_INCLUDENEWFILE: case CFGSTATE_INCLUDENEWFILE_OPT: if (strlen (pContext->FileName) == 0) rc = ToolCfgReadCmdLine (pContext); /* The cmd line has to be read into pBuffer */ else rc = ToolCfgReadCfgFile (pContext); /* The cfg file has to be read into pBuffer */ if ((rc == TOOLCFG_ERROR_OPEN_FAILED) && (pContext->State == CFGSTATE_INCLUDENEWFILE_OPT)) { ToolCfgLocal.IncludeNestingLevel--; ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; pContext->State = CFGSTATE_GETNEWLINE; } else { CFG_CHK_APP (rc) pTmp = pContext->pActLine; CFG_CHK_APP (ToolCfgGetLineLen (pContext)) pContext->State = CFGSTATE_CHECKEOF; } break; case CFGSTATE_GETNEWLINE: CFG_CHK_APP (ToolCfgSearchLine (pContext)) pContext->State = CFGSTATE_CHECKEOF; break; case CFGSTATE_CHECKEOF: pTmp = pContext->pActLine; if ((*pTmp == '\0') || (*pTmp == CHAR_EOF)) { if (pContext->SectionNesting != 0) { pContext->pActLine = NULL; CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement %s before end of file.", KEYWORD_SECTIONEND)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgDropContext (pContext)) ToolCfgLocal.IncludeNestingLevel--; if (ToolCfgLocal.IncludeNestingLevel == -1) /* did we leave the last nesting level */ { pTmp = NULL; pContext->pActLine = NULL; pContext->ActLineLen = 0; pContext->State = CFGSTATE_COMPLETED; } else { ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; pContext->State = CFGSTATE_GETNEWLINE; } } else pContext->State = CFGSTATE_CHECKINCLUDE; break; case CFGSTATE_CHECKINCLUDE: for ( pKeyWord = pTmp; (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } ChkInclude = ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_INCLUDE , (t_int) strlen (KEYWORD_INCLUDE )) == 0; ChkIncludeOpt = ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_INCLUDE_OPT, (t_int) strlen (KEYWORD_INCLUDE_OPT)) == 0; if (ChkInclude || ChkIncludeOpt) { if (++ToolCfgLocal.IncludeNestingLevel >= ToolCfgLocal.MaxIncludeNestingLevel) return TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW; pEol = pContext->pActLine + pContext->ActLineLen; TmpChar = *pEol; *pEol = '\0'; /* set to 0 to have sscanf stop at the end of line */ ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[ToolCfgLocal.IncludeNestingLevel]; pContext = ToolCfgLocal.pActCfgContext; if (ChkIncludeOpt) { pContext->State = CFGSTATE_INCLUDENEWFILE_OPT; pFirstWord = pKeyWord + strlen (KEYWORD_INCLUDE_OPT); } else { pContext->State = CFGSTATE_INCLUDENEWFILE; pFirstWord = pKeyWord + strlen (KEYWORD_INCLUDE); } // Initialize for parameter scanning ParamLen = 0; RemLineLen = strlen (pFirstWord); // Get the filename CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) ToolCfgStrMaxCpy (&pContext->FileName[0], pFirstWord, min(MAX_FILENAME_LEN, ParamLen+1)); RemLineLen -= ParamLen; // Get the section names for (i=0; ;i++) { CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) if (pFirstWord == NULL) break; if (i >= MAX_SECTIONNAMES) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Too many parameters for keyword %s or %s", KEYWORD_INCLUDE, KEYWORD_INCLUDE_OPT)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: %s [SectionName1] [SectionName2] ... [SectionName16]", KEYWORD_INCLUDE)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) ToolCfgStrMaxCpy (&(pContext->SectionNameArr[i][0]), pFirstWord, min(MAX_SECTIONNAME_LEN, ParamLen)+1); RemLineLen -= ParamLen; } *pEol = TmpChar; while (iSectionNameArr[i++])[0] = '\0'; pContext->SectionNesting = 0; } else pContext->State = CFGSTATE_CHECKSECTION; break; case CFGSTATE_CHECKSECTION: for ( pKeyWord = pTmp; /* lint ?????????? */ (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } if (ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_SECTIONSTART, (t_int) strlen (KEYWORD_SECTIONSTART)) == 0) { // if (pContext->SectionNesting >0) // { // CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) // CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "SECTION statements are not allowed to be nested within one file.")) // return TOOLCFG_ERROR_CONFIG_ERROR; // } pFirstWord = pKeyWord + strlen (KEYWORD_SECTIONSTART); RemLineLen = strlen (pFirstWord); CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) if (pFirstWord == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Section name expected.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: SECTION [SectionName1] [SectionName2] ...")) return TOOLCFG_ERROR_CONFIG_ERROR; } SectionNameFound = FALSE; while (pFirstWord != NULL) { CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) TmpChar = pFirstWord[ParamLen]; pFirstWord[ParamLen] = '\0'; for (i=0; (iSectionNameArr[i][0]), pFirstWord) == 0); // pFirstWord may have less chars than SectionNameArr[i], } // but in that case, ToolCfgStrCmpNoCase will no return 0 (eq) if (!SectionNameFound) { for (i=0; (iSectionNesting++; pContext->State = CFGSTATE_GETNEWLINE; } else { pContext->State = CFGSTATE_SEARCHSECTIONEND; } } else { pContext->State = CFGSTATE_CHECKSECTIONEND; } break; case CFGSTATE_CHECKSECTIONEND: KeyLen = (t_int) strlen (KEYWORD_SECTIONEND); for ( pKeyWord = pTmp; /* lint: ???? */ (*pKeyWord == ' ') || (*pKeyWord == '\t'); pKeyWord++) { } if (ToolCfgStrNCmpNoCase (pKeyWord, KEYWORD_SECTIONEND, KeyLen) == 0) { CFG_CHK_APP (ToolCfgNoFurtherParamsExpected (pKeyWord + KeyLen, "ENDSECTION requires no parameters.")) if (pContext->SectionNesting <= 0) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "No corresponding SECTION statement encountered.")) return TOOLCFG_ERROR_CONFIG_ERROR; } else { pContext->SectionNesting--; pContext->State = CFGSTATE_GETNEWLINE; } } else pContext->State = CFGSTATE_LINEREAD; break; case CFGSTATE_SEARCHSECTIONEND: KeyLenSectionStart = (t_int) strlen (KEYWORD_SECTIONSTART); KeyLenSectionEnd = (t_int) strlen (KEYWORD_SECTIONEND ); for (SectionSubNesting = 0;;) { CFG_CHK_APP (ToolCfgSearchLine (pContext)) if (*pContext->pActLine == '\0') { pContext->pActLine = NULL; CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement ENDSECTION before end of file.")) return TOOLCFG_ERROR_CONFIG_ERROR; } pTmp = pContext->pActLine; while ((*pTmp != '\0') && ((*pTmp == ' ') || (*pTmp == '\t'))) pTmp++; if (ToolCfgStrNCmpNoCase (pTmp, KEYWORD_SECTIONEND, KeyLenSectionEnd) == 0) { CFG_CHK_APP (ToolCfgNoFurtherParamsExpected (pTmp + KeyLenSectionEnd, "ENDSECTION requires no parameters.")) if (SectionSubNesting == 0) { pContext->State = CFGSTATE_GETNEWLINE; break; } SectionSubNesting--; } else if (ToolCfgStrNCmpNoCase (pTmp, KEYWORD_SECTIONSTART, KeyLenSectionStart) == 0) { SectionSubNesting++; } } break; default: return TOOLCFG_ERROR_INVALID_STATE; } } pContext->State = CFGSTATE_GETNEWLINE; /* This will be our task on the next call of this function */ *ppLine = pContext->pActLine; *pLineLen = pContext->ActLineLen; return NO_ERROR; } /* ----------------------------------- */ /* Conversion functions */ /* ----------------------------------- */ static APIRET ToolCfgConvertpParamToHMS (t_pchar pParam, t_int /*ParamLen*/, t_pint pValue) { t_int rc; t_int Hour, Min, Sec; if (((pParam[0] >= '0') && (pParam[0] <= '9'))) { rc = sscanf (pParam, "%d:%d:%d", &Hour, &Min, &Sec); if (rc!=3) { Sec = 0; rc = sscanf (pParam, "%d:%d", &Hour, &Min); // Check reduced HH:MM format if (rc!=2) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hh:mm:ss value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } *pValue = Hour*3600 + Min*60 + Sec; // convert to seconds } else { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid entry, hh:mm:ss expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToInteger (t_pchar pParam, t_int ParamLen, t_pint pValue, t_pint pDecConv) { t_int rc; t_int i; t_int MinLen; if ( ((pParam[0] == '0') && ((pParam[1] == 'x') || (pParam[1] == 'X'))) || (pParam[0] == '$')) { if (pParam[0] == '$') MinLen = 1; else MinLen = 2; for (i=MinLen; i= '0') && (pParam[i] <= '9')) && !((pParam[i] >= 'a') && (pParam[i] <= 'f')) && !((pParam[i] >= 'A') && (pParam[i] <= 'F'))) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hexadecimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } if (ParamLen > MinLen) rc = sscanf (&pParam[MinLen], "%x", pValue); else rc = 0; if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid hexadecimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pDecConv=FALSE; } else if (((pParam[0] >= '0') && (pParam[0] <= '9')) || (pParam[0] == '-')) { for (i=1; i '9')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid decimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } } rc = sscanf (pParam, "%d", pValue); if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid decimal value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pDecConv=TRUE; } else { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid entry, decimal or hexadecimal number expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToDouble (t_pchar pParam, t_int ParamLen, t_pdouble pValue) { t_int rc; long double LongDoubleVal; t_pchar pOldLocale; t_pchar pSavedLocale; t_int i; t_int DecimalPoint; t_int Exponent; // Check all the chars in the param to detect entry errors // Convert ',' to '.' DecimalPoint = FALSE; Exponent = FALSE; for (i=0; i '9')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+i)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid character encountered")) return TOOLCFG_ERROR_CONFIG_ERROR; } } // switch the 'locale' to accept '.' as decimal point, // scan the double value and switch back. pOldLocale = setlocale (LC_NUMERIC, NULL); pSavedLocale = strdup (pOldLocale); (void) setlocale (LC_NUMERIC, "C"); rc = sscanf (pParam, "%LG", &LongDoubleVal); (void) setlocale (LC_NUMERIC, pSavedLocale); free (pSavedLocale); if (rc!=1) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid double value.")) return TOOLCFG_ERROR_CONFIG_ERROR; } *pValue = (t_double) LongDoubleVal; return NO_ERROR; } static APIRET ToolCfgReadParameterHMS (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_int Value; t_int MinVal, MaxVal; CFG_CHK_APP (ToolCfgConvertpParamToHMS (pParam, ParamLen, &Value)) if ((Value < (t_int)pCfgDataDesc->MinValue) || (Value > (t_int)pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) MinVal = (t_int)pCfgDataDesc->MinValue; MaxVal = (t_int)pCfgDataDesc->MaxValue; pFormatStr = "Value out of range: %02d:%02d:%02d <= %s <= %02d:%02d:%02d"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, MinVal/3600, (MinVal/60)%60, MinVal%60, pCfgDataDesc->pName, MaxVal/3600, (MaxVal/60)%60, MaxVal%60)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgReadParameterInteger (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_int Value; t_int DecConv; /* To check whether a decimal or hexadecimal conversion had be performed */ CFG_CHK_APP (ToolCfgConvertpParamToInteger (pParam, ParamLen, &Value, &DecConv)) if ((Value < (t_int)pCfgDataDesc->MinValue) || (Value > (t_int)pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) if (DecConv) pFormatStr = "Value out of range: %d <= %s <= %d"; else pFormatStr = "Value out of range: 0x%X <= %s <= 0x%X"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, (t_int)pCfgDataDesc->MinValue, pCfgDataDesc->pName, (t_int)pCfgDataDesc->MaxValue)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgReadParameterDouble (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pcchar pFormatStr; t_double Value; CFG_CHK_APP (ToolCfgConvertpParamToDouble (pParam, ParamLen, &Value)) if ((Value < pCfgDataDesc->MinValue) || (Value > pCfgDataDesc->MaxValue)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) pFormatStr = "Value out of range: %G <= %s <= %G"; CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pFormatStr, pCfgDataDesc->MinValue, pCfgDataDesc->pName, pCfgDataDesc->MaxValue)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) *((t_pdouble)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = Value; return NO_ERROR; } static APIRET ToolCfgConvertpParamToString (t_pchar pParam, t_int ParamLen, t_pchar *ppString, t_pint pStringLen) { if (pParam[0] != STRING_DELIMITER) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String expected. Use %c %c as string delimiters.", STRING_DELIMITER, STRING_DELIMITER)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (pParam[ParamLen-1] != STRING_DELIMITER) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam+ParamLen-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String exceeds end of line, use %c %c as string delimiters, or %c to append next line.", STRING_DELIMITER, STRING_DELIMITER, CHAR_APPEND_LINE)) return TOOLCFG_ERROR_CONFIG_ERROR; } *ppString = pParam+1; *pStringLen = ParamLen-2; return NO_ERROR; } static APIRET ToolCfgReadParameterString (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_pchar pString; t_int StringLen; t_pchar pDest; t_int Src, Dst; CFG_CHK_APP (ToolCfgConvertpParamToString (pParam, ParamLen, &pString, &StringLen)) if (StringLen > pCfgDataDesc->DestLen) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "String too long. The maximum length of the string is %d", pCfgDataDesc->DestLen)) return TOOLCFG_ERROR_CONFIG_ERROR; } if (Assign) { /* Copy the string, replace duplicate '' by single' */ pDest = (t_pchar)pCfgDataDesc->DestAddr + BaseAddr; for (Src=0, Dst=0; SrcDestAddr + BaseAddr, pString, (size_t) StringLen); // ((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)[StringLen] = '\0'; } return NO_ERROR; } static APIRET ToolCfgConvertpParamToSet (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, t_pint pSetValue) { t_pchar pTmp; t_int i; t_int Len; t_pToolCfgSet pSetArray; pSetArray = pCfgDataDesc->pSetArray; for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) break; /* end of array */ if (ParamLen == (t_int)strlen (pSetArray[i].pSetString)) if (ToolCfgStrNCmpNoCase (pSetArray[i].pSetString, pParam, ParamLen) == 0) break; /* set entry found */ } if (pSetArray[i].pSetString == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (pParam)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid set value.")) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, pTmp, &Len)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pTmp)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgHelpBuff)) return TOOLCFG_ERROR_CONFIG_ERROR; } *pSetValue = pSetArray[i].SetValue; return NO_ERROR; } static APIRET ToolCfgReadParameterSet (t_pchar pParam, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { t_int SetValue; CFG_CHK_APP (ToolCfgConvertpParamToSet (pParam, ParamLen, pCfgDataDesc, &SetValue)) if (Assign) *((t_pint)((t_pchar)pCfgDataDesc->DestAddr + BaseAddr)) = SetValue; return NO_ERROR; } static APIRET ToolCfgReadParameter0 (t_pchar pFirstParamChar, t_int ParamLen, t_pToolCfgDataDesc pCfgDataDesc, long BaseAddr, t_int Assign) { if (BaseAddr == (long)INT_MIN) Assign = FALSE; switch (pCfgDataDesc->CfgType) { case CFGTYPE_INTEGER: CFG_CHK_APP (ToolCfgReadParameterInteger (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_DOUBLE : CFG_CHK_APP (ToolCfgReadParameterDouble (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_STRING : CFG_CHK_APP (ToolCfgReadParameterString (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_SET : CFG_CHK_APP (ToolCfgReadParameterSet (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_HMS : CFG_CHK_APP (ToolCfgReadParameterHMS (pFirstParamChar, ParamLen, pCfgDataDesc, BaseAddr, Assign)) break; case CFGTYPE_NULL : break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } return NO_ERROR; } /* ---------------------------------------------- */ /* Table scanning functions */ /* ---------------------------------------------- */ APIRET ToolCfgAddGlobalSectionName (t_pcchar pSectionName) { t_int i; if (strlen (pSectionName) > MAX_SECTIONNAME_LEN) return TOOLCFG_ERROR_SECTIONNAME_TOO_LONG; for (i=0; i=MAX_GLOBALSECTIONNAMES) return TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES; return NO_ERROR; } APIRET ToolCfgDelGlobalSectionName (t_pcchar pSectionName) { t_int i; if (strlen (pSectionName) > MAX_SECTIONNAME_LEN) return TOOLCFG_ERROR_SECTIONNAME_TOO_LONG; for (i=0; i=MAX_GLOBALSECTIONNAMES) return TOOLCFG_ERROR_SECTIONNAME_NOTFOUND; return NO_ERROR; } static APIRET ToolCfgScanTableAnalyseLine (t_pToolCfgTableDesc pCfgTableDesc, t_pchar pFirstWord, t_int RemLineLen, long BaseAddr, t_pint pLineOk) { t_int i; t_int ParamLen; t_pToolCfgDataDesc pCfgDataDesc; *pLineOk = FALSE; /* printf ("\r\nTable entry: %*.*s", RemLineLen, RemLineLen, pFirstWord); */ if (RemLineLen == 0) return NO_ERROR; ParamLen = 0; for (i=0; ;i++) { pCfgDataDesc = &pCfgTableDesc->pDataDescArray[i]; if (pCfgDataDesc->pName == NULL) break; /* Array ends here */ CFG_CHK_APP (ToolCfgFindFirstWord (pFirstWord + ParamLen, (const char **) &pFirstWord, RemLineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgGetParamLen (pFirstWord, &ParamLen)) CFG_CHK_APP (ToolCfgReadParameter0 (pFirstWord, ParamLen, pCfgDataDesc, BaseAddr, TRUE)) } *pLineOk = TRUE; return NO_ERROR; } static APIRET ToolCfgScanTable (t_pchar pActLine, t_int LineLen, t_pToolCfgTableDesc pCfgTableDescArray) { t_pchar pFirstWord; t_int RemLineLen; t_int i, rcs, Eq; t_int LineOk; t_int Found; t_pchar pTableType; t_pchar pTableName; long BaseAddr; t_pcchar pErrorText; t_char TmpChar; t_pToolCfgTableDesc pCfgTableDesc = NULL; TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTableType, 64, MEM_OPT_NONE, MemIdCfgTableType)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTableName, 64, MEM_OPT_NONE, MemIdCfgTableName)) CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pFirstWord, LineLen, &RemLineLen)) rcs = sscanf (pActLine, "%*s %s %s", pTableType, pTableName); if (rcs != 2) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid parameters for keyword %s", KEYWORD_TABLESTART)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The correct syntax is: %s ", KEYWORD_TABLESTART)) return TOOLCFG_ERROR_CONFIG_ERROR; } Found = FALSE; if (pCfgTableDescArray != NULL) { for (i=0; ;i++) { pCfgTableDesc = &pCfgTableDescArray[i]; if (pCfgTableDesc->pTableType == NULL) /* End of array reached? */ break; if (ToolCfgStrCmpNoCase(pCfgTableDesc->pTableType, pTableType) == 0) /* Table type found? */ { Found = TRUE; break; } } } if (!Found) { CFG_CHK_APP (ToolCfgStdErrorHeader (pFirstWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid table type: %s", pTableType)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP ((*pCfgTableDesc->pStartFn) (pTableName, &BaseAddr, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } pActLine[LineLen] = TmpChar; for (LineLen=0;;) { CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; if (pActLine == NULL) { CFG_CHK_APP (ToolCfgStdErrorHeader (NULL)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Missing statement %s before end of file.", KEYWORD_TABLEEND)) return TOOLCFG_ERROR_CONFIG_ERROR; } CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pFirstWord, LineLen, &RemLineLen)) CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_TABLEEND, pFirstWord, RemLineLen, &Eq, NULL)) if (Eq) { if (pCfgTableDesc->pEndFn) { CFG_CHK_APP ((*pCfgTableDesc->pEndFn) (&pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } pActLine[LineLen] = TmpChar; break; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_REMARK, pFirstWord, RemLineLen, &Eq, NULL)) if (!Eq) { CFG_CHK_APP (ToolCfgScanTableAnalyseLine (pCfgTableDesc, pFirstWord, RemLineLen, BaseAddr, &LineOk)) if (LineOk) { CFG_CHK_APP ((*pCfgTableDesc->pSaveAndNextFn) (&BaseAddr, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pActLine)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } } pActLine[LineLen] = TmpChar; } CFG_CHK_APP (ToolCfgMemFree (pTableType, MemIdCfgTableType)) CFG_CHK_APP (ToolCfgMemFree (pTableName, MemIdCfgTableName)) return NO_ERROR; } /* ---------------------------------------------- */ /* Parameter scanning functions */ /* ---------------------------------------------- */ static APIRET ToolCfgCheckAssignment (t_pchar pKeyWord, t_pToolCfgParamDesc pCfgParamDesc, t_pint pAssign) { t_ToolCfgAssignment AssignSource; t_ToolCfgAssignment AssignCount; AssignSource = (t_ToolCfgAssignment)(pCfgParamDesc->Assign & CFGASN_SOURCE); AssignCount = (t_ToolCfgAssignment)(pCfgParamDesc->Assign & CFGASN_COUNT ); if ((AssignSource == CFGASN_CMD) && !ToolCfgScanningCmdLine()) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is not allowed in configuration file (only on command line).")) return TOOLCFG_ERROR_CONFIG_ERROR; } if ((AssignSource == CFGASN_CFG) && ToolCfgScanningCmdLine()) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is not allowed on command line (only in configuration file).")) return TOOLCFG_ERROR_CONFIG_ERROR; } if ((AssignCount == CFGASN_ONCE) && ((pCfgParamDesc->CfgAssignments + pCfgParamDesc->CmdAssignments) >= 1)) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is only allowed once")) return TOOLCFG_ERROR_CONFIG_ERROR; } if (AssignCount == CFGASN_TWICE) { if (((pCfgParamDesc->CfgAssignments>0) && !ToolCfgScanningCmdLine()) || ((pCfgParamDesc->CmdAssignments>0) && ToolCfgScanningCmdLine())) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Assignment for this parameter is only allowed once in configuration file.")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The assignment in configuration file may be replaced by a command line")) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "assignment")) return TOOLCFG_ERROR_CONFIG_ERROR; } } if (ToolCfgScanningCmdLine()) *pAssign = TRUE; else *pAssign = pCfgParamDesc->CmdAssignments ? FALSE : TRUE; return NO_ERROR; } static APIRET ToolCfgCheckEqualSign (t_pcchar pNextChar, t_pcchar *ppFirstParamChar) { while (((*pNextChar == ' ') || (*pNextChar == '\t')) && (*pNextChar != '\0')) pNextChar++; if ((*pNextChar == '\0') || (*pNextChar != '=')) { CFG_CHK_APP (ToolCfgStdErrorHeader (pNextChar-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Equal sign '=' expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } for ( *ppFirstParamChar = pNextChar+1; ((**ppFirstParamChar == ' ') || (**ppFirstParamChar == '\t')) && (**ppFirstParamChar != '\0'); ( *ppFirstParamChar)++) { } if (**ppFirstParamChar == '\0') { CFG_CHK_APP (ToolCfgStdErrorHeader ((*ppFirstParamChar)-1)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter expected.")) return TOOLCFG_ERROR_CONFIG_ERROR; } return NO_ERROR; } static APIRET ToolCfgReadParameter (t_pchar pKeyWord, t_pchar pNextChar, t_pToolCfgParamDesc pCfgParamDesc) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pFirstParamChar; t_pchar pErrorText; t_int Assign; t_int ParamLen; if (pCfgParamDesc) CFG_CHK_APP (ToolCfgCheckAssignment (pKeyWord, pCfgParamDesc, &Assign)) pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->CfgType == CFGTYPE_PRESENCE) { CFG_CHK_APP (ToolCfgCheckIfNoParam (pNextChar)) *((t_pint)(pCfgParamDesc->DataDesc.DestAddr)) = TRUE; } else { CFG_CHK_APP (ToolCfgCheckEqualSign (pNextChar, (const char **) &pFirstParamChar)) CFG_CHK_APP (ToolCfgCheckIfOnlyOneParam (pFirstParamChar, &ParamLen)) CFG_CHK_APP (ToolCfgReadParameter0 (pFirstParamChar, ParamLen, pCfgDataDesc, 0, Assign)) } if (Assign) { if (ToolCfgScanningCmdLine()) pCfgParamDesc->CmdAssignments++; else pCfgParamDesc->CfgAssignments++; } if (pCfgParamDesc->pCallOnInitFn) { CFG_CHK_APP ((*pCfgParamDesc->pCallOnInitFn)(pCfgParamDesc, &pErrorText)) if (pErrorText) { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, pErrorText)) return TOOLCFG_ERROR_CONFIG_ERROR; } } return NO_ERROR; } static APIRET ToolCfgAnalyseEntry (t_pchar pActLine, t_int LineLen, t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { t_pchar pKeyWord; t_pchar pNextChar; t_pToolCfgDataDesc pCfgDataDesc; t_int i; t_int RemLineLen; t_int Eq, EqDef, EqUnDef; t_char TmpChar; t_pchar pSectionName; t_int SectionNameLen; APIRET rc; if (LineLen <=0) /* it's an empty line, unnecessary to continue */ return NO_ERROR; TmpChar = pActLine[LineLen]; /* set end of line to '\0' to ease processing */ pActLine[LineLen] = '\0'; CFG_CHK_APP (ToolCfgFindFirstWord (pActLine, (const char **) &pKeyWord, LineLen, &RemLineLen)) if (pKeyWord == NULL) // Were there just spaces or tabs in this line ? { pActLine[LineLen] = TmpChar; return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_TABLESTART, pKeyWord, RemLineLen, &Eq, NULL)) if (Eq) { pActLine[LineLen] = TmpChar; CFG_CHK_APP (ToolCfgScanTable(pActLine, LineLen, pTableDescArray)) return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_REMARK, pKeyWord, RemLineLen, &Eq, NULL)) if (Eq) { pActLine[LineLen] = TmpChar; return NO_ERROR; } CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_DEFINE , pKeyWord, RemLineLen, &EqDef , &pSectionName)) if (!EqDef) CFG_CHK_APP (ToolCfgCompareKeyWord (KEYWORD_UNDEFINE, pKeyWord, RemLineLen, &EqUnDef, &pSectionName)) if (EqDef || EqUnDef) { while (((*pSectionName == ' ') || (*pSectionName == '\t')) && (*pSectionName != '\0')) pSectionName++; CFG_CHK_APP (ToolCfgCheckIfOnlyOneParam (pSectionName, &SectionNameLen)) pActLine[LineLen] = TmpChar; TmpChar = pSectionName[SectionNameLen]; pSectionName[SectionNameLen] = '\0'; if (EqDef) rc = ToolCfgAddGlobalSectionName (pSectionName); else rc = ToolCfgDelGlobalSectionName (pSectionName); switch (rc) { case TOOLCFG_ERROR_SECTIONNAME_TOO_LONG : CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Section name too long (Max. %d characters).", MAX_SECTIONNAME_LEN)) return TOOLCFG_ERROR_CONFIG_ERROR; case TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES: CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Too many global section names defined (Max. is %d).", MAX_GLOBALSECTIONNAMES)) return TOOLCFG_ERROR_CONFIG_ERROR; case TOOLCFG_ERROR_SECTIONNAME_NOTFOUND: CFG_CHK_APP (ToolCfgStdErrorHeader (pSectionName)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "The section name %s is not defined.", pSectionName)) return TOOLCFG_ERROR_CONFIG_ERROR; default: CFG_CHK_APP (rc) } pSectionName[SectionNameLen] = TmpChar; return NO_ERROR; } Eq = FALSE; if (pParamDescArray != NULL) { for (i=0; ; i++) { pCfgDataDesc = &pParamDescArray[i].DataDesc; if (pCfgDataDesc->pName == NULL) break;/* end of array */ CFG_CHK_APP (ToolCfgCompareKeyWord (pCfgDataDesc->pName, pKeyWord, RemLineLen, &Eq, &pNextChar)) if (Eq) { CFG_CHK_APP (ToolCfgReadParameter (pKeyWord, pNextChar, &pParamDescArray[i])) break; } } } if (!Eq) /* keyword not found in table */ { CFG_CHK_APP (ToolCfgStdErrorHeader (pKeyWord)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Invalid keyword.")) return TOOLCFG_ERROR_CONFIG_ERROR; } pActLine[LineLen] = TmpChar; return NO_ERROR; } /* CfgFreeContextBuffers: Free all context buffers that are still in use */ static APIRET ToolCfgFreeContextBuffers (void) { t_pToolCfgContext pCfgContext; t_int i; for (i=ToolCfgLocal.IncludeNestingLevel; i>0; i--) { pCfgContext = &ToolCfgLocal.pCfgContextStack[i]; if (pCfgContext->pBuffer) CFG_CHK_APP (ToolCfgMemFree (pCfgContext->pBuffer, MemIdCfgBuffer)) } return NO_ERROR; } static APIRET ToolCfgScanParams (t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { t_pchar pActLine; t_int LineLen; APIRET rc; CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) rc = NO_ERROR; while (pActLine && !rc) { rc = ToolCfgAnalyseEntry(pActLine, LineLen, pParamDescArray, pTableDescArray); if (!rc) CFG_CHK_APP (ToolCfgGetNextLine (&pActLine, &LineLen)) } CFG_CHK_APP (ToolCfgFreeContextBuffers()) CFG_CHK_APP (rc) return NO_ERROR; } static APIRET ToolCfgScanSource (t_pcchar pFileName, t_pcchar pSectionName, t_pToolCfgParamDesc pParamDescArray, t_pToolCfgTableDesc pTableDescArray) { APIRET rc; t_int ContextStackSize; t_int i; ContextStackSize = ToolCfgLocal.MaxIncludeNestingLevel * (t_int) sizeof (t_ToolCfgContext); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&ToolCfgLocal.pCfgContextStack, (t_uint)ContextStackSize, MEM_OPT_NONE, MemIdCfgContextStack)) ToolCfgLocal.pActCfgContext = &ToolCfgLocal.pCfgContextStack[0]; ToolCfgLocal.IncludeNestingLevel = 0; /* initialise first context stack entry */ ToolCfgLocal.pActCfgContext->BufferLen = 0; ToolCfgLocal.pActCfgContext->ActLineNr = 0; ToolCfgLocal.pActCfgContext->pActLine = NULL; ToolCfgLocal.pActCfgContext->pBuffer = NULL; ToolCfgLocal.pActCfgContext->SectionNesting = 0; ToolCfgLocal.pActCfgContext->State = CFGSTATE_INCLUDENEWFILE; CFG_CHK_APP (ToolCfgCopyName (pFileName , & ToolCfgLocal.pActCfgContext->FileName [0] , MAX_FILENAME_LEN )) CFG_CHK_APP (ToolCfgCopyName (pSectionName, &(ToolCfgLocal.pActCfgContext->SectionNameArr[0][0]), MAX_SECTIONNAME_LEN)) for (i=1; iSectionNameArr[i][0] = '\0'; rc = ToolCfgScanParams (pParamDescArray, pTableDescArray); CFG_CHK_APP (ToolCfgMemFree (ToolCfgLocal.pCfgContextStack, MemIdCfgContextStack)) CFG_CHK_APP (rc) return NO_ERROR; } /* CfgCheckInitialisation: Check whether all parameters have been initialized. */ static APIRET ToolCfgCheckInitialisation(t_pToolCfgParamDesc pParamDescArray) { t_int i, Err; t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; Err = FALSE; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) break; /* end of array reached */ if (( pCfgParamDesc->CfgAssignments == 0 ) && ( pCfgParamDesc->CmdAssignments == 0 ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_NULL ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_PRESENCE) && // Parameters of type 'presence' are always optional ((pCfgParamDesc->Assign & CFGASN_OPTIONAL) == 0 )) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Configuration error: Parameter %s has not been initialized.", pCfgDataDesc->pName)) Err = TRUE; } } if (Err) return TOOLCFG_ERROR_CONFIG_ERROR; return NO_ERROR; } static APIRET ToolCfgLogGetSetName (t_pToolCfgSet pSetArray, t_int SetValue, t_pcchar *ppSetString) { t_int i; *ppSetString = NULL; for (i=0; ; i++) { if (pSetArray[i].pSetString == NULL) break; /* end of array */ if (pSetArray[i].SetValue == SetValue) { *ppSetString = pSetArray[i].pSetString; break; } } return NO_ERROR; } static APIRET ToolCfgPrintContents (t_pchar pBuff, t_pToolCfgParamDesc pCfgParamDesc) { t_pToolCfgDataDesc pCfgDataDesc; t_pchar pSetString; t_int Hms; t_int SetValue; if ((pCfgParamDesc->CfgAssignments == 0) && (pCfgParamDesc->CmdAssignments == 0)) { sprintf (pBuff, "not initialized"); } else { pCfgDataDesc = &pCfgParamDesc->DataDesc; switch (pCfgDataDesc->CfgType) { case CFGTYPE_PRESENCE:sprintf (pBuff, "%s" , *(int *)pCfgDataDesc->DestAddr ? "present" : "not present"); break; case CFGTYPE_INTEGER: sprintf (pBuff, "%d (0x%X)", *(int *)pCfgDataDesc->DestAddr, *(int *)pCfgDataDesc->DestAddr); break; case CFGTYPE_DOUBLE: sprintf (pBuff, "%G" , *(double*)pCfgDataDesc->DestAddr); break; case CFGTYPE_STRING: sprintf (pBuff, "%s" , (char *)pCfgDataDesc->DestAddr); break; case CFGTYPE_SET: SetValue = *(int *)pCfgDataDesc->DestAddr; CFG_CHK_APP (ToolCfgLogGetSetName (pCfgDataDesc->pSetArray, SetValue, (const char **) &pSetString)) if (pSetString == NULL) sprintf (pBuff, "Set str unknown for value %d", SetValue); else sprintf (pBuff, "%s", pSetString); break; case CFGTYPE_HMS: Hms = (*(int *)pCfgDataDesc->DestAddr); sprintf (pBuff, "%02d:%02d:%02d", Hms/3600, (Hms/60)%60, Hms%60); break; case CFGTYPE_NULL: break; default: return TOOLCFG_ERROR_INVALID_CFGTYPE; } } return NO_ERROR; } APIRET ToolCfgPrintParamContents (t_pToolCfgParamDesc pParamDescArray, t_pchar pName, t_pchar pBuff) { t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; t_int i; if (pBuff) pBuff[0] = '\0'; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) return TOOLCFG_ERROR_UNKNOWN_PARAMETER; if (ToolCfgStrCmpNoCase (pCfgDataDesc->pName, pName) == 0) { if (pBuff) CFG_CHK_APP (ToolCfgPrintContents (pBuff, pCfgParamDesc)) break; } } return NO_ERROR; } /* ToolCfgLogConfiguration: Write all the configuration parameters with their values to the log file */ APIRET ToolCfgLogConfiguration (t_pToolCfgParamDesc pParamDescArray) { t_pToolCfgParamDesc pCfgParamDesc; t_pToolCfgDataDesc pCfgDataDesc; t_pchar pBuff; t_int i, Err; t_int wr; CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pBuff, 4096, MEM_OPT_NONE, MemIdCfgLogConfiguration)) Err = FALSE; for (i=0; ;i++) { pCfgParamDesc = &pParamDescArray[i]; pCfgDataDesc = &pCfgParamDesc->DataDesc; if (pCfgDataDesc->pName == NULL) break; /* end of array reached */ if (( pCfgParamDesc->CfgAssignments == 0 ) && ( pCfgParamDesc->CmdAssignments == 0 ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_NULL ) && ( pCfgParamDesc->DataDesc.CfgType != CFGTYPE_PRESENCE) && // Parameters of type 'presence' are always optional ((pCfgParamDesc->Assign & CFGASN_OPTIONAL) == 0 )) { CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "Parameter %s has not been initialized.", pCfgDataDesc->pName)) Err = TRUE; } else { wr = sprintf (pBuff, "%s = ", pCfgDataDesc->pName); CFG_CHK_APP (ToolCfgPrintContents (&pBuff[wr], pCfgParamDesc)) CFG_CHK_APP (ToolCfgLogEntry(__FFL__, "%s", pBuff)) } } CFG_CHK_APP (ToolCfgMemFree (pBuff, MemIdCfgLogConfiguration)) if (Err) return TOOLCFG_ERROR_CONFIG_ERROR; return NO_ERROR; } /* ToolCfgResetAssignCounters: Reset all assignment counters for all keywords */ static APIRET ToolCfgResetAssignCounters (t_pToolCfgParamDesc pParamDescArray) { t_int i; for (i=0; ; i++) { if (pParamDescArray[i].DataDesc.pName == NULL) break; /* end of array reached */ pParamDescArray[i].CmdAssignments = 0; pParamDescArray[i].CfgAssignments = 0; } return NO_ERROR; } /* CfgGetCmdLineOption: Read an option from the command line. This function is */ /* usually called to get the configuration or log file name. */ APIRET ToolCfgGetCmdLineOption (t_pcchar pParamName, t_pcchar *ppValue) { t_int i, Eq; t_int LineLen = 0; t_pchar pNextChar = NULL; t_ToolCfgContext CfgContext; *ppValue = NULL; Eq = 0; for (i=1; i 0) && (LineFlag)) { LineLen = (t_int) strlen (pRemark); rcp = fprintf (pFile, "\r\n%*s%s ", Indent, "", KEYWORD_REMARK); CFG_CHK_FPRINTF(rcp) for (i=0; ipName == NULL) break; /* end of array reached */ Source = (t_ToolCfgAssignment) (pParamDescArray[i].Assign & CFGASN_SOURCE); if (((Source & CFGASN_CMD) && !(Source & CFGASN_CFG) && (CfgParams == FALSE)) || ((Source & CFGASN_CFG) && (CfgParams == TRUE ))) { CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp1, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildHelp (pCfgDataDesc, pTmp1, &Len)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n %s", pTmp1)) CFG_CHK_APP (ToolCfgMemFree (pTmp1, MemIdCfgHelpBuff)) (*pEntries)++; } } } if (CfgParams && pTableDescArray) { for (i=0; ; i++) { pCfgTableDesc = &pTableDescArray[i]; if (pCfgTableDesc->pTableType == NULL) break; /* end of array reached */ CFG_CHK_APP (ToolCfgBuildTableHelp (pCfgTableDesc, NULL, NULL, &Len)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp1, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp2, (t_uint)Len, MEM_OPT_NONE, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgBuildTableHelp (pCfgTableDesc, pTmp1, pTmp2, &Len)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n %s %s ", KEYWORD_TABLESTART, pCfgTableDesc->pTableType)) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp1, 6, TRUE )) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp2, 6, FALSE)) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n %s", KEYWORD_TABLEEND)) CFG_CHK_APP (ToolCfgMemFree (pTmp1, MemIdCfgHelpBuff)) CFG_CHK_APP (ToolCfgMemFree (pTmp2, MemIdCfgHelpBuff)) (*pEntries)++; } } return NO_ERROR; } APIRET ToolCfgBuildTemplate (t_pcchar pFileName, t_pcchar pComment, t_pcchar pSectionName, t_ToolCfgParamDesc *pParamDescArray, t_ToolCfgTableDesc *pTableDescArray) { FILE *pFile; t_int Entries, rc; t_pchar pTmp; const t_int TmpLen = 256; struct tm *NowTM; time_t NowT; pFile = fopen(pFileName, "wb"); if (pFile == NULL) return TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED; setbuf (pFile, NULL); CFG_CHK_APP (ToolCfgMemAlloc ((void **)&pTmp, TmpLen, MEM_OPT_NONE, MemIdCfgTemplateHeader)) (void) time (&NowT); NowTM = localtime (&NowT); rc = sprintf (pTmp, "Configuration file template, created on "); (void) strftime (pTmp+rc, (size_t)(TmpLen-rc), "%d/%m/%Y %H:%M:%S", NowTM); CFG_CHK_APP (ToolCfgEnterRemark (pFile, pTmp, 0, TRUE)) CFG_CHK_APP (ToolCfgMemFree (pTmp, MemIdCfgTemplateHeader)) if(pComment) CFG_CHK_APP (ToolCfgEnterRemark (pFile, pComment, 0, TRUE)) if (pSectionName) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n%s %s\r\n", KEYWORD_SECTIONSTART, pSectionName)) CFG_CHK_APP (ToolCfgBuildTemplate0 (pFile, TRUE, &Entries, pParamDescArray, pTableDescArray)) if (pSectionName) CFG_CHK_FPRINTF (fprintf (pFile, "\r\n\r\n%s", KEYWORD_SECTIONEND)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) CFG_CHK_APP (ToolCfgEnterRemark (pFile, "Options, that can only be entered on command line", 0, TRUE)) CFG_CHK_APP (ToolCfgBuildTemplate0 (pFile, FALSE, &Entries, pParamDescArray, pTableDescArray)) if (Entries == 0) CFG_CHK_APP (ToolCfgEnterRemark (pFile, "There are no such options", 0, FALSE)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) CFG_CHK_APP (ToolCfgEnterEmptyLine (pFile)) rc = fclose(pFile); if (rc) return TOOLCFG_ERROR_CLOSE_FAILED; return NO_ERROR; } /* ToolCfgSetErrLogFn: The application can specify the desired logging */ /* function here (for example vprintf, or an own function). */ APIRET ToolCfgSetLogFn (t_pToolCfgUserLogFn pUserLogFn) { ToolCfgLocal.pUserLogFn = pUserLogFn; return NO_ERROR; } APIRET ToolCfgGetSetString (t_pToolCfgSet pSetArray, int SetValue, const char **ppSetString) { t_pToolCfgSet pSet; *ppSetString = NULL; for (pSet = &pSetArray[0]; pSet->pSetString != NULL; pSet++) { if (pSet->SetValue == SetValue) { *ppSetString = pSet->pSetString; break; } } return NO_ERROR; } /* ------------------------------ */ /* Module initialisation */ /* ------------------------------ */ static int IsInit = 0; APIRET ToolCfgInit (int argc, char *argv[]) { if(IsInit == 1) return NO_ERROR; IsInit = 1; CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (ERROR_BASE_TOOL_CFG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_OPEN_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_READ_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CLOSE_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SEEKEND_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SEEKSET_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_STATE )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_NAME_TOO_LONG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INCLUDE_NESTING_OVERFLOW )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CONFIG_ERROR )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_ASSIGNMENT_OPTION)) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_INVALID_CFGTYPE )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_TEMPLATE_OPEN_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_FPRINTF_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_CMDLINE_OPTION_NOT_FOUND )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_MALLOC_FAILED )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SECTIONNAME_TOO_LONG )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_TOO_MANY_SECTIONNAMES )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_SECTIONNAME_NOTFOUND )) CFG_CHK_APP (TOOL_ERROR_REGISTER_CODE (TOOLCFG_ERROR_UNKNOWN_PARAMETER )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgBuffer )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgErrorHeader )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgContextStack )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTemplateHeader )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpBuff )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpString )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpInt )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgHelpTable )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTableType )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgTableName )) CFG_CHK_APP (MEM_REGISTER_MEMID (MemIdCfgLogConfiguration)) ToolCfgLocal.argc = argc; ToolCfgLocal.argv = argv; ToolCfgLocal.pUserLogFn = NULL; ToolCfgLocal.MaxIncludeNestingLevel = MAX_CFG_NESTING_LEVEL; memset (&ToolCfgLocal.GlobalSectionNameArr[0], 0, sizeof (ToolCfgLocal.GlobalSectionNameArr)); return NO_ERROR; } APIRET ToolCfgUseAdjustedCommandLine (int argc, char *argv[]) { ToolCfgLocal.argc = argc; ToolCfgLocal.argv = argv; return NO_ERROR; } APIRET ToolCfgDeInit (void) { if(IsInit == 0) return NO_ERROR; CFG_CHK_APP (ToolCfgFreeContextBuffers ()) IsInit = 0; return NO_ERROR; } libguytools2-2.0.5/toolerror.cpp000066400000000000000000000224341322376377300167310ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Error handling // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #include #include #include #include #include "toolconstants.h" #include "toolglobalid.h" #include "toolerror.h" /* ------------------------------ */ /* Type & structure definitions */ /* ------------------------------ */ typedef struct { int ErrorCode; const char *pMsg; } t_ToolErrorEntry, *t_pToolErrorEntry; typedef struct { t_pToolErrorLogFn pLogFn; t_pToolErrorEntry pErrorCodeArr; int ErrorCodeArrEntries; int ErrorCodeArrLen; } t_ToolErrorLocal; /* ------------------------------ */ /* Variables */ /* ------------------------------ */ static t_ToolErrorLocal ToolErrorLocal; static int Initialised = FALSE; APIRET ToolErrorLog (const char *pFileName, const char *pFunctionName, int LineNr, const char * pFormat, ...) { va_list VaList; va_start(VaList, pFormat); if (ToolErrorLocal.pLogFn != NULL) { ToolErrorLocal.pLogFn (pFileName, pFunctionName, LineNr, pFormat, VaList); } else { printf ("\nError in %s, %s, %d:", pFileName, pFunctionName, LineNr); vprintf (pFormat, VaList); } va_end(VaList); return NO_ERROR; } /* ------------------------------ */ /* Functions */ /* ------------------------------ */ static APIRET ToolErrorFindEntry (int ErrorCode, t_pToolErrorEntry *ppEntry) { t_pToolErrorEntry pEntry = NULL; int i; for (i=0; iErrorCode == ErrorCode) break; } if (i >= ToolErrorLocal.ErrorCodeArrEntries) return TOOL_ERROR_ENTRY_NOT_FOUND; if (ppEntry) *ppEntry = pEntry; return NO_ERROR; } APIRET ToolErrorRegisterError (int ErrorCode, const char *pMsg) { t_pToolErrorEntry pEntry; if (Initialised == FALSE) return TOOL_ERROR_NOT_INITIALISED; APIRET rc = ToolErrorFindEntry (ErrorCode, NULL); if (rc == TOOL_ERROR_ENTRY_NOT_FOUND) { pEntry = &(ToolErrorLocal.pErrorCodeArr[ToolErrorLocal.ErrorCodeArrEntries++]); pEntry->ErrorCode = ErrorCode; pEntry->pMsg = pMsg; } else { ToolErrorLog (__FFL__, "Duplicate ErrorCode %d", ErrorCode); return TOOL_ERROR_DUPLICATE_ENTRY; } return NO_ERROR; } APIRET ToolErrorGetMessage (int ErrorCode, const char **ppMsg) { if (ErrorCode == NO_ERROR) { *ppMsg = "NO_ERROR"; } else { t_pToolErrorEntry pEntry; APIRET rc = ToolErrorFindEntry (ErrorCode, &pEntry); if (rc == TOOL_ERROR_ENTRY_NOT_FOUND) *ppMsg = NULL; else *ppMsg = pEntry->pMsg; } return NO_ERROR; } const char *ToolErrorMessage (int ErrorCode) { static char TmpStr [20]; // Attention: This is not multi-threading compatible!! const char *pMsg; APIRET rc = ToolErrorGetMessage (ErrorCode, &pMsg); if (rc != NO_ERROR) { snprintf(TmpStr, sizeof(TmpStr), "[%d]", ErrorCode); pMsg = TmpStr; } return pMsg; } APIRET ToolErrorCheck (char const *pFileName, char const *pFunctionName, int LineNr, int ErrorCode) { const char *pMsg; if (ErrorCode == NO_ERROR) { ToolErrorLog (pFileName, pFunctionName, LineNr, "%s called with Rc=0", __FUNCTION__); } else { APIRET rc = ToolErrorGetMessage (ErrorCode, &pMsg); switch (rc) { case NO_ERROR: ToolErrorLog(pFileName, pFunctionName, LineNr, "Error %d: %s", ErrorCode, pMsg); break; case TOOL_ERROR_ENTRY_NOT_FOUND: ToolErrorLog(pFileName, pFunctionName, LineNr, "Error %d: -- unregistered error code --", ErrorCode); break; default: ToolErrorLog(__FFL__, "Unexpected internal error %ld...", rc); ToolErrorLog(__FFL__, "...while trying to log problem %d coming from %s/%s/%d", ErrorCode, pFileName, pFunctionName, LineNr); break; } } return NO_ERROR; } APIRET ToolErrorSetLogFn (t_pToolErrorLogFn pLogFn) { ToolErrorLocal.pLogFn = pLogFn; return NO_ERROR; } const char *ToolErrorTranslateErrno (int Errno) { const char *pTxt; switch (Errno) { case EPERM : pTxt = "Operation not permitted"; break; case ENOENT : pTxt = "No such file or directory"; break; case ESRCH : pTxt = "No such process"; break; case EINTR : pTxt = "Interrupted system call"; break; case EIO : pTxt = "I/O error"; break; case ENXIO : pTxt = "No such device or address"; break; case E2BIG : pTxt = "Argument list too long"; break; case ENOEXEC: pTxt = "Exec format error"; break; case EBADF : pTxt = "Bad file number"; break; case ECHILD : pTxt = "No child processes"; break; case EAGAIN : pTxt = "Try again"; break; case ENOMEM : pTxt = "Out of memory"; break; case EACCES : pTxt = "Permission denied"; break; case EFAULT : pTxt = "Bad address"; break; case ENOTBLK: pTxt = "Block device required"; break; case EBUSY : pTxt = "Device or resource busy"; break; case EEXIST : pTxt = "File exists"; break; case EXDEV : pTxt = "Cross-device link"; break; case ENODEV : pTxt = "No such device"; break; case ENOTDIR: pTxt = "Not a directory"; break; case EISDIR : pTxt = "Is a directory"; break; case EINVAL : pTxt = "Invalid argument"; break; case ENFILE : pTxt = "File table overflow"; break; case EMFILE : pTxt = "Too many open files"; break; case ENOTTY : pTxt = "Not a typewriter"; break; case ETXTBSY: pTxt = "Text file busy"; break; case EFBIG : pTxt = "File too large"; break; case ENOSPC : pTxt = "No space left on device"; break; case ESPIPE : pTxt = "Illegal seek"; break; case EROFS : pTxt = "Read-only file system"; break; case EMLINK : pTxt = "Too many links"; break; case EPIPE : pTxt = "Broken pipe"; break; case EDOM : pTxt = "Math argument out of domain of func"; break; case ERANGE : pTxt = "Math result not representable"; break; default : pTxt = "toolerror.coo: None of the standard error codes"; break; } return pTxt; } /* --------------------------------------------------------------------------------- */ /* Module initialisation */ /* --------------------------------------------------------------------------------- */ APIRET ToolErrorInit (int MaxErrors) { if (Initialised == TRUE) return TOOL_ERROR_ALREADY_INITIALISED; ToolErrorLocal.pErrorCodeArr = (t_pToolErrorEntry) malloc (MaxErrors * sizeof(t_ToolErrorEntry)); ToolErrorLocal.ErrorCodeArrLen = MaxErrors; ToolErrorLocal.ErrorCodeArrEntries = 0; Initialised = TRUE; return NO_ERROR; } APIRET ToolErrorDeInit () { if (Initialised == FALSE) return TOOL_ERROR_NOT_INITIALISED; free (ToolErrorLocal.pErrorCodeArr); ToolErrorLocal.pLogFn = NULL; Initialised = FALSE; return NO_ERROR; } libguytools2-2.0.5/toollog.cpp000077500000000000000000000123021322376377300163550ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Log utility // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #include #include #include #include #include #include #include #include #include "toolglobalid.h" #include "toolerror.h" #include "toollog.h" // ----------- // Constants // ----------- const char * LogLevelLookup [t_Log::Entries] = {"Debug", "Info", "Error"}; const int LOG_HEADER_LEN = 75; const char LibGuyToolsVersion[] = LIBGUYTOOLS_VERSION; // ----------------- // Local variables // ----------------- static bool LogInitialised = false; static QMutex LogMutex; static char *pLogFilename; static char LogLineHeader[512]; t_Log::t_Log (const char* pFileName, APIRET &rc) { if (!LogInitialised) { LogInitialised = true; pLogFilename = (char *) malloc (strlen (pFileName)+1); strcpy (pLogFilename, pFileName); Entry (Info, __FFL__, "Log file opened"); rc = NO_ERROR; } else { rc = TOOLLOG_ERROR_INITIALISED_TWICE; } } t_Log::~t_Log(void) { Entry (Info, __FFL__, "Log file closed"); free (pLogFilename); LogInitialised = false; } bool t_Log::IsInitialised (void) { return LogInitialised; } void t_Log::GetLibGuyToolsVersion (const char **pVersion) { *pVersion = LibGuyToolsVersion; } void t_Log::vEntry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { time_t NowT; struct tm *pNowTM; FILE *pFile; int wr; static bool LogFileError = false; // Variable prevents us from repetitive log error messages time (&NowT); pNowTM = localtime (&NowT); LogMutex.lock(); wr = strftime (&LogLineHeader[0] , sizeof(LogLineHeader) , "%a %d.%b.%Y %H:%M:%S ", pNowTM); wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%08X ", (unsigned int)pthread_self()); // wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%4d ", getpid()); // getpid returns alyways the same number if (pFileName && pFunctionName) wr += snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%s %s %d", pFileName, pFunctionName, LineNr); while (wr < LOG_HEADER_LEN) LogLineHeader[wr++] = ' '; snprintf (&LogLineHeader[wr], sizeof(LogLineHeader)-wr, "%-5s - ", LogLevelLookup[Level]); if (LogInitialised) { pFile = fopen64 (pLogFilename, "a"); if (pFile == NULL) { if (!LogFileError) printf ("\nLog file error: Can't be opened"); LogFileError = true; } else { LogFileError = false; fprintf (pFile, "%s", &LogLineHeader[0]); vfprintf (pFile, pFormat, pArguments); fprintf (pFile, "\n"); fclose (pFile); } } if (!LogInitialised || (pFile == NULL)) { printf ("\n"); printf ("%s", &LogLineHeader[0]); vprintf (pFormat, pArguments); } LogMutex.unlock(); } void t_Log::Entry (t_Level Level, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) { va_list VaList; va_start(VaList, pFormat); vEntry (Level, pFileName, pFunctionName, LineNr, pFormat, VaList); va_end(VaList); } void t_Log::vEntryInfo (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Info, pFileName, pFunctionName, LineNr, pFormat, pArguments); } void t_Log::vEntryDebug (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Debug, pFileName, pFunctionName, LineNr, pFormat, pArguments); } void t_Log::vEntryError (const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments) { vEntry (Error, pFileName, pFunctionName, LineNr, pFormat, pArguments); } libguytools2-2.0.5/tools.pro000066400000000000000000000020621322376377300160530ustar00rootroot00000000000000TEMPLATE = lib DESTDIR = ./lib TARGET = guytools include( ./libguytools_version.pro.inc ) # The following line allows the software to see its own version # (just for logging purpose). Many slashes and quotes... look at # result of it during compilation DEFINES += "LIBGUYTOOLS_VERSION=\\\""$$VERSION"\\\"" # Use the standard Qt configuration but remove the GUI part, as we do not need it. CONFIG += qt QT -= gui CONFIG += warn_on thread release DEFINES += TOCFG_COMPILE_FOR_USE_WITHOUT_TOOLBOX DEPENDPATH += ./include INCLUDEPATH += ./include QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS *= $(shell dpkg-buildflags --get LDFLAGS) QMAKE_CXXFLAGS_WARN_ON += -Wno-strict-aliasing # Switch off warning "dereferencing type-punned pointer will break strict-aliasing rules" QMAKE_CXXFLAGS_WARN_ON += -fmessage-length=0 # Tell g++ not to split messages into different lines QMAKE_CXXFLAGS_RELEASE += -O3 SOURCES += toollog.cpp SOURCES += toolerror.cpp SOURCES += toolsysinfo.cpp SOURCES += toolsignal.cpp SOURCES += toolcfg.cpp libguytools2-2.0.5/toolsignal.cpp000066400000000000000000000266361322376377300170650ustar00rootroot00000000000000// **************************************************************************** // Project: libguytools // **************************************************************************** // Programmer: Guy Voncken // Police Grand-Ducale // Service de Police Judiciaire // Section Nouvelles Technologies // **************************************************************************** // Module: Signal handler with backtrace // **************************************************************************** // Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Guy Voncken // // This file is part of libguytools. // // libguytools is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // libguytools is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with libguytools. If not, see . #include #include #include //#define __USE_GNU #include #include //#define __USE_XOPEN #include #include #include #include "tooltypes.h" #include "toolglobalid.h" #include "toolsignal.h" #include "toolerror.h" // ------------------------------------ // Type definitions // ------------------------------------ typedef struct { t_pToolSignalLogFn pLogFn; t_pToolSignalHandler pSignalHandlerFn; struct sigaction SignalActionDefault; } t_ToolSignalLocal; // ------------------------------------ // Module variables // ------------------------------------ bool ToolSignalInitialised = false; t_ToolSignalLocal ToolSignalLocal; // ------------------------------------ // Log functions // ------------------------------------ static int ToolSignalLogEntry (bool Error, const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, ...) { va_list VaList; va_start(VaList, pFormat); if (ToolSignalLocal.pLogFn) { (*ToolSignalLocal.pLogFn)(Error, pthread_self(), pFileName, pFunctionName, LineNr, pFormat, VaList); } else { printf ("\n"); vprintf (pFormat, VaList); } va_end(VaList); return NO_ERROR; } // ------------------------------------ // Main functions // ------------------------------------ static void ToolSignalStandardSet (sigset_t *pSignalSet) { sigfillset (pSignalSet); // Add all known signals to set, except the ones listed below: sigdelset (pSignalSet, SIGSEGV); // - handled by our backtrace function, see below sigdelset (pSignalSet, SIGPIPE); // - which would cause problems in ceratin situations when our program deals with pipes sigdelset (pSignalSet, SIGWINCH); // - emitted on window resize sigdelset (pSignalSet, SIGCHLD); // - QProcess relies on receiving this one in order to know when a child process finishes } // These settings will be valid for the current thread and all its children threads. That's the reason, why // ToolSignalInit should be called in the application main thread before starting any other thread. static void *ToolSignalThread (void *p) { sigset_t SignalSet; int Signal; bool Exit; char *pSignalName; p=p; // Dummy statement to avoid compiler warning about unused p ToolSignalLogEntry (false, __FFL__, "Signal guard thread started with id %d", getpid()); Exit = false; while (!Exit) { ToolSignalStandardSet (&SignalSet); sigwait (&SignalSet, &Signal); // wait for any signal in given set // when we get here, we've caught a signal // --------------------------------------- pSignalName = strsignal(Signal); ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Caught signal: %s", getpid(), pthread_self(), pSignalName); if (ToolSignalLocal.pSignalHandlerFn) (*ToolSignalLocal.pSignalHandlerFn) (Signal); switch (Signal) { case SIGTERM: case SIGINT : Exit = true; break; default: break; } } ToolSignalLogEntry (true, __FFL__, "Stopping signal guard thread."); return NULL; } // ToolSignalBacktraceHandler is called by any // thread in the program causing a segment violation. static void ToolSignalBacktraceHandler (int Signal, siginfo_t *pSignalInfo, void *pSecret) { const int TraceArrLen = 50; char **ppMessages; void *TraceArr[TraceArrLen]; int TraceSize; int i; static int RecursiveCallDetection = 0; /* Code below is no longer needed. According to tests on amd64 and i386 on Ubuntu 14.04, the address of the place the where exception occured nowadays is correctly included in the array data returned by backtrace(). It thus seems to be no longer necessary to separately fetch and add the instruction pointer corresponding to the segmentation fault. This wasn't the case on older systems, see for example http://www.linuxjournal.com/article/6391?page=0,1 . void *pIP = NULL; #if defined(__sparc__) struct sigcontext* pSigContext = (struct sigcontext*) pSecret; #if __WORDSIZE == 64 pIP = (void*) pSigContext->sigc_regs.tpc ; #else pIP = (void*) pSigContext->si_regs.pc ; #endif #else ucontext_t* pUContext = (ucontext_t*) pSecret; #if defined(__i386__) pIP = (void*) pUContext->uc_mcontext.gregs[REG_EIP]; #elif defined(__x86_64__) pIP = (void*) pUContext->uc_mcontext.gregs[REG_RIP]; #elif defined(__hppa__) pIP = (void*) pUContext->uc_mcontext.sc_iaoq[0] & ~0x3UL; #elif (defined (__ppc__)) || (defined (__powerpc__)) pIP = (void*) pUContext->uc_mcontext.regs->nip; #elif defined(__arm__) pIP = (void*) pUContext->uc_mcontext.arm_pc; #elif defined(__aarch64__) pIP = (void*) pUContext->uc_mcontext.pc; #endif #endif */ RecursiveCallDetection++; switch (RecursiveCallDetection) { case 1: ppMessages = NULL; ToolSignalLogEntry (true, __FFL__, "----------------------------------------------------------------------"); if (Signal == SIGSEGV) { ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Got signal '%s' (%d), faulty address is %p" /*, "from %p" */, // See remarks above getpid(), pthread_self(), strsignal(Signal), Signal, pSignalInfo->si_addr /*, pIP*/); } else { ToolSignalLogEntry (true, __FFL__, "Thread (%d-%d): Got signal '%s' (%d) -- strange, function should only be called on SIGSEGV.", getpid(), pthread_self(), strsignal(Signal), Signal); } TraceSize = backtrace (TraceArr, TraceArrLen); /* TraceArr[1] = pIP; */ // See remarks above ppMessages = backtrace_symbols (TraceArr, TraceSize); ToolSignalLogEntry (true, __FFL__, "Backtrace execution path"); ToolSignalLogEntry (true, __FFL__, "The first two entries are normally related to the signal handler."); ToolSignalLogEntry (true, __FFL__, "The faulty code generally is referenced by the 3rd line in the listing below."); for (i=0; i. #include #include #include #include #include #include #include #include #include //#include #include #include "toolconstants.h" #include "toolglobalid.h" #include "toolerror.h" #include "toolsysinfo.h" // ------------------------------------ // Constants // ------------------------------------ // ------------------------------------ // Type definitions // ------------------------------------ // ------------------------------------ // Local variables // ------------------------------------ static bool ToolSysInfoInitialized = false; // ------------------------------------ // Functions // ------------------------------------ APIRET ToolSysInfoGetMacAddr (t_pToolSysInfoMacAddr pMacAddr) { struct ifreq Ifr; struct ifreq *pIfr; struct ifconf Ifc; char buf[1024]; int s, i, wr; bool ok = false; s = socket(AF_INET, SOCK_DGRAM, 0); if (s==-1) return TOOLSYSINFO_ERROR_SOCKET; Ifc.ifc_len = sizeof(buf); Ifc.ifc_buf = buf; ioctl(s, SIOCGIFCONF, &Ifc); pIfr = Ifc.ifc_req; for (i = Ifc.ifc_len / sizeof(struct ifreq); --i >= 0; pIfr++) { strcpy (Ifr.ifr_name, pIfr->ifr_name); if (ioctl (s, SIOCGIFFLAGS, &Ifr) == 0) { if (! (Ifr.ifr_flags & IFF_LOOPBACK)) { if (ioctl(s, SIOCGIFHWADDR, &Ifr) == 0) { ok = true; break; } } } } close(s); if (!ok) return TOOLSYSINFO_ERROR_NO_ADDR; bcopy (Ifr.ifr_hwaddr.sa_data, &pMacAddr->AddrVal[0], TOOLSYSINFO_MACADDRLEN_VAL); wr = 0; for (int i=0; iAddrStr[wr], "%02X", pMacAddr->AddrVal[i]); return NO_ERROR; } APIRET ToolSysInfoUname (QString &Uname) { struct utsname name; if (uname (&name) == -1) return TOOLSYSINFO_ERROR_UNAME; Uname = QString(name.sysname) + " " + name.nodename + " " + name.release + " " + name.version + " " + name.machine; return NO_ERROR; } // ------------------------------ // Module initialisation // ------------------------------ APIRET ToolSysInfoInit (void) { if (ToolSysInfoInitialized) return TOOLSYSINFO_ALREADY_INITIALISED; TOOL_CHK (TOOL_ERROR_REGISTER_CODE (ERROR_BASE_TOOL_SYSINFO)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ALREADY_INITIALISED)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_SOCKET)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_NO_ADDR)) TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_UNAME)) ToolSysInfoInitialized = true; return NO_ERROR; } APIRET ToolSysInfoDeInit (void) { return NO_ERROR; } libguytools2-2.0.5/trunk.pro000066400000000000000000000000301322376377300160470ustar00rootroot00000000000000include( ./tools.pro )