/* * Copyright (c) 2002, The Tendra Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * Crown Copyright (c) 1997 * * This TenDRA(r) Computer Program is subject to Copyright * owned by the United Kingdom Secretary of State for Defence * acting through the Defence Evaluation and Research Agency * (DERA). It is made available to Recipients with a * royalty-free licence for its use, reproduction, transfer * to other parties and amendment for any purpose not excluding * product development provided that any such use et cetera * shall be deemed to be acceptance of the following conditions:- * * (1) Its Recipients shall ensure that this Notice is * reproduced upon any copies or amended versions of it; * * (2) Any amended version of it shall be clearly marked to * show both the nature of and the organisation responsible * for the relevant amendment or amendments; * * (3) Its onward transfer from a recipient to another * party shall be deemed to be that party's acceptance of * these conditions; * * (4) DERA gives no warranty or assurance as to its * quality or suitability for any purpose and DERA accepts * no liability whatsoever in relation to any use to which * it may be put. * * $TenDRA: tendra/src/tools/tspec/name.c,v 1.9 2004/08/08 08:50:21 stefanf Exp $ */ #include "config.h" #include "cstring.h" #include #include "object.h" #include "hash.h" #include "name.h" #include "type.h" #include "utility.h" #include "variable.h" /* * STANDARD FLAGS * * These flags are set by the command-line options and determine the * action of the program. */ BoolT allow_long_long = 0; BoolT force_output = 0; BoolT local_input = 0; BoolT restrict_depth = 1; BoolT restrict_use = 0; BoolT unique_names = 0; int verbose = 0; /* * INPUT AND OUTPUT DIRECTORIES * * The variable input_dir consists of a colon-separated list of directories * to be searched for input files. output_incl_dir and output_src_dir * give respectively the output include and output source directories. * The lengths of these directory names (plus one) are also given. */ char *input_dir = INPUT_DIR; char *output_incl_dir = INCLUDE_DIR; char *output_src_dir = SRC_DIR; int output_incl_len = (int) sizeof (INCLUDE_DIR); int output_src_len = (int) sizeof (SRC_DIR); /* * FIND THE BASENAME OF A FILE NAME * * This routine returns the basename (i.e. just the final component) of * the filename nm. */ char * basename(char *nm) { char *b = nm; for (; *nm; nm++) { if (*nm == '/') b = nm + 1; } return (b); } /* * FIND THE DIRECTORY COMPONENT OF A FILE NAME * * This routine returns a copy of the directory component of the filename * nm. */ char * dirname(char *nm) { char *p, *end = null; char *dir = string_copy (nm); for (p = dir; *p; p++) { if (*p == '/') end = p; } if (end == null || end == dir) return (null); *end = 0; return (dir); } /* * FIND A RELATIVE PATHNAME * * This routine prints the relative pathname from the file from to the * file to, ignoring the first n characters. */ char * relative(char *from, char *to, int n) { char *s = buffer; if (from == null) return (to); if (to == null) return (from); for (from = from + n; *from; from++) { if (*from == '/') { IGNORE strcpy (s, "../"); s += 3; } } IGNORE strcpy (s, to + n); return (buffer); } /* * HACK A NAME * * This routine hacks the name nm according to the given key. */ char * hack_name(char *nm, char *key) { char *p = string_copy (nm), *q; for (q = p; *q; q++) { char c = *q; if (isalpha (c) && isupper (c)) { /* The second letter of key maps upper case letters */ if (key [1] == 'a') *q = (char) tolower (c); } else if (isalpha (c) && islower (c)) { /* The third letter of key maps lower case letters */ if (key [2] == 'A') *q = (char) toupper (c); } else if (isdigit (c)) { /* The fourth letter of key maps digits */ *q = (char) (c - '0' + key [3]); } else if (strchr (key + 4, c)) { /* The rest of key gives special characters */ } else { /* The first letter of key is the default */ *q = key [0]; } } return (p); } /* * FIND A TOKEN NAME * * This routine makes up a token name for an object named nm. If * unique_names is false this is just nm, otherwise it is prefixed by * a string depending on the current input file. */ char * token_name(char *nm) { if (strneq (nm, HIDDEN_NAME, HIDDEN_LEN)) { nm = string_concat ("~", nm + HIDDEN_LEN); } if (unique_names && crt_object) { info *i = crt_object->u.u_info; char *pfx = i->prefix; if (pfx == null) { pfx = token_prefix (i->api, i->file, i->subset); i->prefix = pfx; } if (*pfx) return (string_printf ("%s.%s", pfx, nm)); } return (nm); } /* * FIND TOKEN PREFIX * * This routine finds the token prefix for the API subset api:file:subset. */ char * token_prefix(char *api, char *file, char *subset) { UNUSED (subset); if (unique_names) { int n; if (file == null) return (api); IGNORE sprintf (buffer, "%s.%s", api, basename (file)); n = (int) strlen (buffer) - 2; if (n >= 0 && buffer [n] == '.') buffer [n] = 0; return (hack_name (buffer, "_Aa0.")); } return (null); } /* * FIND A SUBSET NAME * * This routine finds the name associated with the API subset with API * api, header file and subset subset. */ char * subset_name(char *api, char *file, char *subset) { char *sn; if (subset) { char *f = (file ? file : ""); sn = string_printf ("%s:%s:%s", api, f, subset); } else if (file) { sn = string_printf ("%s:%s", api, file); } else { sn = string_printf ("%s", api); } return (sn); } /* * FIND AN INCLUDE OUTPUT FILE NAME * * This routine finds the include output file name for the API subset * api:file:subset using the directory dir as a base. */ char * include_name(char *dir, char *api, char *file, char *subset) { char *nm; if (subset) { char s [20]; IGNORE strncpy (s, subset, 18); s [OUTPUT_LENGTH] = 0; nm = string_printf (OUTPUT_SUBSET, dir, api, s); } else if (file) { nm = string_printf (OUTPUT_FILE, dir, api, file); } else { nm = string_printf (OUTPUT_API, dir, api); } return (nm); } /* * FIND A SOURCE OUTPUT FILE NAME * * This routine finds the source output file name for the API subset * api:file:subset using the directory dir as a base. */ char * src_name(char *dir, char *api, char *file, char *subset) { char *nm; if (subset) { char s [20]; IGNORE strncpy (s, subset, 18); s [OUTPUT_LENGTH] = 0; nm = string_printf (SOURCE_SUBSET, dir, api, s); } else if (file) { int n; nm = string_printf (SOURCE_FILE, dir, api, basename (file)); n = (int) strlen (nm) - 4; if (n >= 0 && streq (nm + n, ".h.c")) { IGNORE strcpy (nm + n, ".c"); } } else { nm = string_printf (SOURCE_API, dir, api); } return (nm); } /* * FIND A MACRO NAME * * This routine finds the protection (or other) macro for the API subset * api:file:subset using the macro prefix pfx. */ char * macro_name(char *pfx, char *api, char *file, char *subset) { if (subset) { char *f = (file ? file : ""); IGNORE sprintf (buffer, "%s_%s_%s_%s", pfx, api, f, subset); } else if (file) { IGNORE sprintf (buffer, "%s_%s_%s", pfx, api, file); } else { IGNORE sprintf (buffer, "%s_%s", pfx, api); } return (hack_name (buffer, "_AA0")); } /* * FIND A DECLARATION BLOCK NAME * * This routine finds the declaration block name for the API subset * api:file:subset. */ char * block_name(char *api, char *file, char *subset) { char * pfx = (subset ? "subset" : "api"); if (file) { int len; IGNORE sprintf (buffer, "%s__%s__%s", pfx, api, file); /* remove any trailing ".h" */ len = (int) strlen (buffer); if (streq (buffer + len - 2, ".h")) buffer [len - 2] = '\0'; } else { IGNORE sprintf (buffer, "%s__%s", pfx, api); } return (hack_name (buffer, "_Aa0")); }