mirror of https://github.com/wb2osz/direwolf.git
Fix ttgrid corner and various cleanups.
This commit is contained in:
parent
4f6ca0d389
commit
e108147655
|
@ -1283,13 +1283,26 @@ static int parse_location (char *e)
|
|||
|
||||
lat0 = tt_config.ttloc_ptr[ipat].grid.lat0;
|
||||
lat9 = tt_config.ttloc_ptr[ipat].grid.lat9;
|
||||
double yrange = lat9 - lat0;
|
||||
y = atof(ystr);
|
||||
m_latitude = lat0 + y * (lat9-lat0) / (pow(10., strlen(ystr)) - 1.);
|
||||
|
||||
double user_y_max = round(pow(10., strlen(ystr)) - 1.); // e.g. 999 for 3 digits
|
||||
m_latitude = lat0 + yrange * y / user_y_max;
|
||||
#if 0
|
||||
dw_printf ("TTLOC_GRID LAT min=%f, max=%f, range=%f\n", lat0, lat9, yrange);
|
||||
dw_printf ("TTLOC_GRID LAT user_y=%f, user_y_max=%f\n", y, user_y_max);
|
||||
dw_printf ("TTLOC_GRID LAT min + yrange * user_y / user_y_range = %f\n", m_latitude);
|
||||
#endif
|
||||
lon0 = tt_config.ttloc_ptr[ipat].grid.lon0;
|
||||
lon9 = tt_config.ttloc_ptr[ipat].grid.lon9;
|
||||
double xrange = lon9 - lon0;
|
||||
x = atof(xstr);
|
||||
m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);
|
||||
double user_x_max = round(pow(10., strlen(xstr)) - 1.);
|
||||
m_longitude = lon0 + xrange * x / user_x_max;
|
||||
#if 0
|
||||
dw_printf ("TTLOC_GRID LON min=%f, max=%f, range=%f\n", lon0, lon9, xrange);
|
||||
dw_printf ("TTLOC_GRID LON user_x=%f, user_x_max=%f\n", x, user_x_max);
|
||||
dw_printf ("TTLOC_GRID LON min + xrange * user_x / user_x_range = %f\n", m_longitude);
|
||||
#endif
|
||||
|
||||
m_dao[2] = e[0];
|
||||
m_dao[3] = e[1];
|
||||
|
@ -1972,6 +1985,7 @@ static const struct {
|
|||
/* Latitude comes out ok, 37.9137 -> 55.82 min. */
|
||||
/* Longitude -81.1254 -> 8.20 min */
|
||||
{ "B21234*A67979#", "679", "12", "7A", "", "", "12.3400", "56.1200", "!TB2!" },
|
||||
|
||||
{ "B533686*A67979#", "679", "12", "7A", "", "", "37.9222", "81.1143", "!TB5!" },
|
||||
|
||||
// TODO: should test other coordinate systems.
|
||||
|
|
|
@ -886,7 +886,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
|
|||
|
||||
decode_aprs_t A;
|
||||
|
||||
decode_aprs (&A, pp, 0);
|
||||
decode_aprs (&A, pp, 0, 0);
|
||||
|
||||
// Temp experiment to see how different systems set the RR bits in the source and destination.
|
||||
// log_rr_bits (&A, pp);
|
||||
|
|
|
@ -350,8 +350,9 @@ void ax25_delete (packet_t this_p)
|
|||
* strict - True to enforce rules for packets sent over the air.
|
||||
* False to be more lenient for packets from IGate server.
|
||||
*
|
||||
* Messages from an IGate server can have longer
|
||||
* Packets from an IGate server can have longer
|
||||
* addresses after qAC. Up to 9 observed so far.
|
||||
* The SSID can be 2 alphanumeric characters, not just 1 to 15.
|
||||
*
|
||||
* We can just truncate the name because we will only
|
||||
* end up discarding it. TODO: check on this.
|
||||
|
@ -740,6 +741,7 @@ packet_t ax25_dup (packet_t copy_from)
|
|||
* alphanumeric characters for the SSID.
|
||||
* We also get messages like this from a server.
|
||||
* KB1POR>APU25N,TCPIP*,qAC,T2NUENGLD:...
|
||||
* K1BOS-B>APOSB,TCPIP,WR2X-2*:...
|
||||
*
|
||||
* 2 (extra true) will complain if * is found at end.
|
||||
*
|
||||
|
@ -1983,6 +1985,7 @@ void ax25_format_addrs (packet_t this_p, char *result)
|
|||
}
|
||||
|
||||
ax25_get_addr_with_ssid (this_p, AX25_SOURCE, stemp);
|
||||
// FIXME: For ALL strcat: Pass in sizeof result and use strlcat.
|
||||
strcat (result, stemp);
|
||||
strcat (result, ">");
|
||||
|
||||
|
|
22
src/config.c
22
src/config.c
|
@ -2397,10 +2397,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
*/
|
||||
|
||||
/*
|
||||
* DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | NOID=alias ]
|
||||
* DIGIPEAT from-chan to-chan alias-pattern wide-pattern [ OFF|DROP|MARK|TRACE | ATGP=alias ]
|
||||
*
|
||||
* NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
|
||||
* The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up.
|
||||
* ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
|
||||
* DO NOT put this in the User Guide. On a need to know basis.
|
||||
*/
|
||||
|
||||
|
@ -2527,8 +2526,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
p_digi_config->preempt[from_chan][to_chan] = PREEMPT_TRACE;
|
||||
t = split(NULL,0);
|
||||
}
|
||||
else if (strncasecmp(t, "NOID=", 5) == 0) {
|
||||
strlcpy (p_digi_config->noid[from_chan][to_chan], t+5, sizeof(p_digi_config->noid[from_chan][to_chan]));;
|
||||
else if (strncasecmp(t, "ATGP=", 5) == 0) {
|
||||
strlcpy (p_digi_config->atgp[from_chan][to_chan], t+5, sizeof(p_digi_config->atgp[from_chan][to_chan]));;
|
||||
t = split(NULL,0);
|
||||
}
|
||||
}
|
||||
|
@ -3221,7 +3220,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line);
|
||||
dw_printf ("Line %d: Missing minimum latitude for TTGRID command.\n", line);
|
||||
continue;
|
||||
}
|
||||
tl->grid.lat0 = parse_ll(t,LAT,line);
|
||||
|
@ -3231,7 +3230,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line);
|
||||
dw_printf ("Line %d: Missing minimum longitude for TTGRID command.\n", line);
|
||||
continue;
|
||||
}
|
||||
tl->grid.lon0 = parse_ll(t,LON,line);
|
||||
|
@ -3241,7 +3240,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing latitude for TTGRID command.\n", line);
|
||||
dw_printf ("Line %d: Missing maximum latitude for TTGRID command.\n", line);
|
||||
continue;
|
||||
}
|
||||
tl->grid.lat9 = parse_ll(t,LAT,line);
|
||||
|
@ -3251,13 +3250,16 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing longitude for TTGRID command.\n", line);
|
||||
dw_printf ("Line %d: Missing maximum longitude for TTGRID command.\n", line);
|
||||
continue;
|
||||
}
|
||||
tl->grid.lon0 = parse_ll(t,LON,line);
|
||||
tl->grid.lon9 = parse_ll(t,LON,line);
|
||||
|
||||
/* temp debugging */
|
||||
|
||||
// dw_printf ("CONFIG TTGRID min %f %f\n", tl->grid.lat0, tl->grid.lon0);
|
||||
// dw_printf ("CONFIG TTGRID max %f %f\n", tl->grid.lat9, tl->grid.lon9);
|
||||
|
||||
//for (j=0; j<p_tt_config->ttloc_len; j++) {
|
||||
// dw_printf ("debug ttloc %d/%d %s\n", j, p_tt_config->ttloc_size,
|
||||
// p_tt_config->ttloc_ptr[j].pattern);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017 John Langner, WB2OSZ
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017, 2022 John Langner, WB2OSZ
|
||||
//
|
||||
// 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
|
||||
|
@ -140,6 +140,11 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen);
|
|||
*
|
||||
* quiet - Suppress error messages.
|
||||
*
|
||||
* third_party - True when parsing a third party header.
|
||||
* (decode_aprs is called recursively.)
|
||||
* This is mostly found when an IGate transmits a message
|
||||
* that came via APRS-IS.
|
||||
*
|
||||
* Outputs: A-> g_symbol_table, g_symbol_code,
|
||||
* g_lat, g_lon,
|
||||
* g_speed_mph, g_course, g_altitude_ft,
|
||||
|
@ -151,16 +156,19 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen);
|
|||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
||||
void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party)
|
||||
{
|
||||
//dw_printf ("DEBUG decode_aprs quiet=%d, third_party=%d\n", quiet, third_party);
|
||||
|
||||
char dest[AX25_MAX_ADDR_LEN];
|
||||
//char dest[AX25_MAX_ADDR_LEN];
|
||||
unsigned char *pinfo;
|
||||
int info_len;
|
||||
|
||||
|
||||
info_len = ax25_get_info (pp, &pinfo);
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs info=\"%s\"\n", pinfo);
|
||||
|
||||
memset (A, 0, sizeof (*A));
|
||||
|
||||
A->g_quiet = quiet;
|
||||
|
@ -200,16 +208,26 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
|
||||
if (*pinfo == '}') {
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs recursively process third party header\n");
|
||||
|
||||
// This must not be strict because the addresses in third party payload doesn't
|
||||
// need to adhere to the AX.25 address format (i.e. 6 upper case alphanumeric.)
|
||||
// SSID can be 2 alphanumeric characters.
|
||||
// Addresses can include lower case, e.g. q contruct.
|
||||
|
||||
// e.g. WR2X-2>APRS,WA1PLE-13*:}
|
||||
// K1BOS-B>APOSB,TCPIP,WR2X-2*:@122015z4221.42ND07111.93W&/A=000000SharkRF openSPOT3 MMDVM446.025 MA/SW
|
||||
|
||||
packet_t pp_payload = ax25_from_text ((char*)pinfo+1, 0);
|
||||
if (pp_payload != NULL) {
|
||||
decode_aprs (A, pp_payload, quiet);
|
||||
decode_aprs (A, pp_payload, quiet, 1); // 1 means used recursively
|
||||
ax25_delete (pp_payload);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
strlcpy (A->g_msg_type, "Third Party Header: Unable to parse payload.", sizeof(A->g_msg_type));
|
||||
ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +236,10 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
*/
|
||||
|
||||
ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, A->g_dest);
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs source=%s, dest=%s\n", A->g_src, A->g_dest);
|
||||
|
||||
|
||||
/*
|
||||
* Report error if the information part contains a nul character.
|
||||
|
@ -260,7 +281,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
break;
|
||||
|
||||
default:
|
||||
decode_tocall (A, dest);
|
||||
decode_tocall (A, A->g_dest);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -316,7 +337,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
break;
|
||||
|
||||
|
||||
case ':': /* Message: for one person, a group, or a bulletin. */
|
||||
case ':': /* "Message" (special APRS meaning): for one person, a group, or a bulletin. */
|
||||
/* Directed Station Query */
|
||||
/* Telemetry metadata. */
|
||||
|
||||
|
@ -402,7 +423,17 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
|
||||
if (A->g_symbol_table == ' ' || A->g_symbol_code == ' ') {
|
||||
|
||||
symbols_from_dest_or_src (*pinfo, A->g_src, dest, &A->g_symbol_table, &A->g_symbol_code);
|
||||
// A symbol on a "message" makes no sense and confuses people.
|
||||
// Third party too. Set from the payload.
|
||||
// Maybe eliminate for a couple others.
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs@end1 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo);
|
||||
|
||||
if (*pinfo != ':' && *pinfo != '}') {
|
||||
symbols_from_dest_or_src (*pinfo, A->g_src, A->g_dest, &A->g_symbol_table, &A->g_symbol_code);
|
||||
}
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs@end2 third_party=%d, symbol_table=%c, symbol_code=%c, *pinfo=%c\n", third_party, A->g_symbol_table, A->g_symbol_code, *pinfo);
|
||||
}
|
||||
|
||||
} /* end decode_aprs */
|
||||
|
@ -410,8 +441,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
|
||||
void decode_aprs_print (decode_aprs_t *A) {
|
||||
|
||||
char stemp[200];
|
||||
//char tmp2[2];
|
||||
char stemp[500];
|
||||
double absll;
|
||||
char news;
|
||||
int deg;
|
||||
|
@ -419,11 +449,10 @@ void decode_aprs_print (decode_aprs_t *A) {
|
|||
char s_lat[30];
|
||||
char s_lon[30];
|
||||
int n;
|
||||
char symbol_description[100];
|
||||
|
||||
/*
|
||||
* First line has:
|
||||
* - message type
|
||||
* - packet type
|
||||
* - object name
|
||||
* - symbol
|
||||
* - manufacturer/application
|
||||
|
@ -432,28 +461,53 @@ void decode_aprs_print (decode_aprs_t *A) {
|
|||
*/
|
||||
strlcpy (stemp, A->g_msg_type, sizeof(stemp));
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print stemp1=%s\n", stemp);
|
||||
|
||||
if (strlen(A->g_name) > 0) {
|
||||
strlcat (stemp, ", \"", sizeof(stemp));
|
||||
strlcat (stemp, A->g_name, sizeof(stemp));
|
||||
strlcat (stemp, "\"", sizeof(stemp));
|
||||
}
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print stemp2=%s\n", stemp);
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print symbol_code=%c=0x%02x\n", A->g_symbol_code, A->g_symbol_code);
|
||||
|
||||
if (A->g_symbol_code != ' ') {
|
||||
char symbol_description[100];
|
||||
symbols_get_description (A->g_symbol_table, A->g_symbol_code, symbol_description, sizeof(symbol_description));
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print symbol_description_description=%s\n", symbol_description);
|
||||
|
||||
strlcat (stemp, ", ", sizeof(stemp));
|
||||
strlcat (stemp, symbol_description, sizeof(stemp));
|
||||
}
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print stemp3=%s mfr=%s\n", stemp, A->g_mfr);
|
||||
|
||||
if (strlen(A->g_mfr) > 0) {
|
||||
strlcat (stemp, ", ", sizeof(stemp));
|
||||
strlcat (stemp, A->g_mfr, sizeof(stemp));
|
||||
if (strcmp(A->g_dest, "APRS") == 0) {
|
||||
strlcat (stemp, "\nUse of \"APRS\" in the destination field is obsolete.", sizeof(stemp));
|
||||
strlcat (stemp, " You can help to improve the quality of APRS signals.", sizeof(stemp));
|
||||
strlcat (stemp, "\nTell the sender (", sizeof(stemp));
|
||||
strlcat (stemp, A->g_src, sizeof(stemp));
|
||||
strlcat (stemp, ") to use the proper product code from", sizeof(stemp));
|
||||
strlcat (stemp, " http://www.aprs.org/aprs11/tocalls.txt", sizeof(stemp));
|
||||
}
|
||||
else {
|
||||
strlcat (stemp, ", ", sizeof(stemp));
|
||||
strlcat (stemp, A->g_mfr, sizeof(stemp));
|
||||
}
|
||||
}
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print stemp4=%s\n", stemp);
|
||||
|
||||
if (strlen(A->g_mic_e_status) > 0) {
|
||||
strlcat (stemp, ", ", sizeof(stemp));
|
||||
strlcat (stemp, A->g_mic_e_status, sizeof(stemp));
|
||||
}
|
||||
|
||||
//dw_printf ("DEBUG decode_aprs_print stemp5=%s\n", stemp);
|
||||
|
||||
if (A->g_power > 0) {
|
||||
char phg[100];
|
||||
|
@ -1120,7 +1174,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
|||
char sym_table_id;
|
||||
} *p;
|
||||
|
||||
char dest[10];
|
||||
char dest[12];
|
||||
int ch;
|
||||
int n;
|
||||
int offset;
|
||||
|
@ -1379,7 +1433,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
|||
|
||||
// Last Updated Dec. 2021
|
||||
|
||||
// This does not change very often but I'm wondering if we could simply parse
|
||||
// This does not change very often but I'm wondering if we could parse
|
||||
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
|
||||
|
||||
if (isT(*pfirst)) {
|
||||
|
@ -1511,13 +1565,18 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
|||
* :xxxxxxxxx:EQNS. Telemetry metadata, Equation Coefficients
|
||||
* :xxxxxxxxx:BITS. Telemetry metadata, Bit Sense/Project Name
|
||||
* :xxxxxxxxx:? Directed Station Query
|
||||
* :xxxxxxxxx:ack Message acknowledged (received)
|
||||
* :xxxxxxxxx:rej Message rejected (unable to accept)
|
||||
* :xxxxxxxxx:ackNNNN Message acknowledged (received)
|
||||
* :xxxxxxxxx:rejNNNNN Message rejected (unable to accept)
|
||||
*
|
||||
* :xxxxxxxxx: ... Message with no message number.
|
||||
* (Text may not contain the { character because
|
||||
* it indicates beginning of optional message number.)
|
||||
* :xxxxxxxxx: ... {num Message with message number.
|
||||
* :xxxxxxxxx: ... {NNNNN Message with message number, 1 to 5 alphanumeric.
|
||||
* :xxxxxxxxx: ... {mm} Message with new style message number.
|
||||
* :xxxxxxxxx: ... {mm}aa Message with new style message number and ack.
|
||||
*
|
||||
*
|
||||
* Reference: See new message id style: http://www.aprs.org/aprs11/replyacks.txt
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
|
@ -1528,8 +1587,10 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
|
|||
char dti; /* : */
|
||||
char addressee[9];
|
||||
char colon; /* : */
|
||||
char message[73]; /* 0-67 characters for message */
|
||||
/* Optional { followed by 1-5 characters for message number */
|
||||
char message[256-1-9-1]; /* Officially up to 67 characters for message text. */
|
||||
/* Relaxing seemingly arbitrary restriction here; it doesn't need to fit on a punched card. */
|
||||
/* Wouldn't surprize me if others did not pay attention to the limit. */
|
||||
/* Optional { followed by 1-5 alphanumeric characters for message number */
|
||||
|
||||
/* If the first character is '?' it is a Directed Station Query. */
|
||||
} *p;
|
||||
|
@ -1651,25 +1712,84 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
|
|||
|
||||
/* ack or rej? Message number is required for these. */
|
||||
|
||||
else if (strncmp(p->message,"ack",3) == 0) {
|
||||
else if (strncasecmp(p->message,"ack",3) == 0) {
|
||||
if (strncmp(p->message,"ack",3) != 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("ERROR: \"%s\" must be lower case \"ack\"\n", p->message);
|
||||
}
|
||||
strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number));
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "ACK message %s for \"%s\"", A->g_message_number, addressee);
|
||||
if (strlen(A->g_message_number) == 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("ERROR: Message number is missing after \"ack\".\n");
|
||||
}
|
||||
if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0';
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" ACKnowledged message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee);
|
||||
A->g_message_subtype = message_subtype_ack;
|
||||
}
|
||||
else if (strncmp(p->message,"rej",3) == 0) {
|
||||
else if (strncasecmp(p->message,"rej",3) == 0) {
|
||||
if (strncmp(p->message,"rej",3) != 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("ERROR: \"%s\" must be lower case \"rej\"\n", p->message);
|
||||
}
|
||||
strlcpy (A->g_message_number, p->message + 3, sizeof(A->g_message_number));
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "REJ message %s for \"%s\"", A->g_message_number, addressee);
|
||||
if (strlen(A->g_message_number) == 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("ERROR: Message number is missing after \"rej\".\n");
|
||||
}
|
||||
if (strlen(A->g_message_number) >= 3 && A->g_message_number[2] == '}') A->g_message_number[2] = '\0';
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "\"%s\" REJected message number \"%s\" from \"%s\"", A->g_src, A->g_message_number, addressee);
|
||||
A->g_message_subtype = message_subtype_ack;
|
||||
}
|
||||
|
||||
/* message number is optional here. */
|
||||
// Message to a particular station or a bulletin.
|
||||
// message number is optional here.
|
||||
// Test cases. Wrap in third party too.
|
||||
// A>B::WA1XYX-15:Howdy y'all
|
||||
// A>B::WA1XYX-15:Howdy y'all{12345
|
||||
// A>B::WA1XYX-15:Howdy y'all{12}
|
||||
// A>B::WA1XYX-15:Howdy y'all{12}34
|
||||
// A>B::WA1XYX-15:Howdy y'all{toolong
|
||||
// X>Y:}A>B::WA1XYX-15:Howdy y'all
|
||||
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12345
|
||||
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12}
|
||||
// X>Y:}A>B::WA1XYX-15:Howdy y'all{12}34
|
||||
// X>Y:}A>B::WA1XYX-15:Howdy y'all{toolong
|
||||
|
||||
else {
|
||||
// Look for message number.
|
||||
char *pno = strchr(p->message, '{');
|
||||
if (pno != NULL) {
|
||||
*pno = '\0';
|
||||
int mlen = strlen(pno+1);
|
||||
if (mlen < 1 || mlen > 5) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("Message number \"%s\" has length outside range of 1 to 5.\n", pno+1);
|
||||
}
|
||||
strlcpy (A->g_message_number, pno+1, sizeof(A->g_message_number));
|
||||
// TODO: Complain if not alphanumeric.
|
||||
|
||||
char ack[8] = "";
|
||||
|
||||
if (mlen >= 3 && A->g_message_number[2] == '}') {
|
||||
// New (1999) style.
|
||||
A->g_message_number[2] = '\0';
|
||||
strlcpy (ack, A->g_message_number + 3, sizeof(ack));
|
||||
}
|
||||
|
||||
if (strlen(ack) > 0) {
|
||||
// With ACK. Message number should be 2 characters.
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\", with ACK for \"%s\"", A->g_message_number, A->g_src, addressee, ack);
|
||||
}
|
||||
else {
|
||||
// Message number can be 1-5 characters.
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, number \"%s\", from \"%s\" to \"%s\"", A->g_message_number, A->g_src, addressee);
|
||||
}
|
||||
}
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message %s for \"%s\"", A->g_message_number, addressee);
|
||||
else {
|
||||
// No message number.
|
||||
snprintf (A->g_msg_type, sizeof(A->g_msg_type), "APRS Message, with no number, from \"%s\" to \"%s\"", A->g_src, addressee);
|
||||
}
|
||||
|
||||
A->g_message_subtype = message_subtype_message;
|
||||
|
||||
/* No location so don't use process_comment () */
|
||||
|
@ -2389,10 +2509,12 @@ static void aprs_telemetry (decode_aprs_t *A, char *info, int ilen, int quiet)
|
|||
|
||||
static void aprs_user_defined (decode_aprs_t *A, char *info, int ilen)
|
||||
{
|
||||
if (strncmp(info, "{tt", 3) == 0) { // Historical. Should probably use DT.
|
||||
if (strncmp(info, "{tt", 3) == 0 || // Historical.
|
||||
strncmp(info, "{DT", 3) == 0) { // Official after registering {D*
|
||||
aprs_raw_touch_tone (A, info, ilen);
|
||||
}
|
||||
else if (strncmp(info, "{mc", 3) == 0) { // Historical. Should probably use DM.
|
||||
else if (strncmp(info, "{mc", 3) == 0 || // Historical.
|
||||
strncmp(info, "{DM", 3) == 0) { // Official after registering {D*
|
||||
aprs_morse_code (A, info, ilen);
|
||||
}
|
||||
else if (info[0] == '{' && info[1] == USER_DEF_USER_ID && info[2] == USER_DEF_TYPE_AIS) {
|
||||
|
@ -4993,7 +5115,7 @@ int main (int argc, char *argv[])
|
|||
ax25_safe_print ((char *)pinfo, info_len, 1); // Display non-ASCII to hexadecimal.
|
||||
dw_printf ("\n");
|
||||
|
||||
decode_aprs (&A, pp, 0); // Extract information into structure.
|
||||
decode_aprs (&A, pp, 0, 0); // Extract information into structure.
|
||||
|
||||
decode_aprs_print (&A); // Now print it in human readable format.
|
||||
|
||||
|
@ -5014,7 +5136,7 @@ int main (int argc, char *argv[])
|
|||
if (pp != NULL) {
|
||||
decode_aprs_t A;
|
||||
|
||||
decode_aprs (&A, pp, 0); // Extract information into structure.
|
||||
decode_aprs (&A, pp, 0, 0); // Extract information into structure.
|
||||
|
||||
decode_aprs_print (&A); // Now print it in human readable format.
|
||||
|
||||
|
|
|
@ -26,9 +26,11 @@ typedef struct decode_aprs_s {
|
|||
|
||||
char g_src[AX25_MAX_ADDR_LEN];
|
||||
|
||||
char g_msg_type[60]; /* APRS data type. Telemetry descriptions get pretty long. */
|
||||
char g_dest[AX25_MAX_ADDR_LEN];
|
||||
|
||||
char g_msg_type[80]; /* APRS data type description. Telemetry descriptions get pretty long. */
|
||||
/* Putting msg in the name was a poor choice because */
|
||||
/* "message" has a specific meaning. Rename it someday. */
|
||||
/* "message" has a specific meaning. Rename it to data_type someday. FIXME */
|
||||
|
||||
char g_symbol_table; /* The Symbol Table Identifier character selects one */
|
||||
/* of the two Symbol Tables, or it may be used as */
|
||||
|
@ -77,7 +79,9 @@ typedef struct decode_aprs_s {
|
|||
message_subtype_directed_query
|
||||
} g_message_subtype; /* Various cases of the overloaded "message." */
|
||||
|
||||
char g_message_number[8]; /* Message number. Should be 1 - 5 characters if used. */
|
||||
char g_message_number[8]; /* Message number. Should be 1 - 5 alphanumeric characters if used. */
|
||||
/* Addendum 1.1 has new format {mm} or {mm}aa with only two */
|
||||
/* characters for message number and an ack riding piggyback. */
|
||||
|
||||
float g_speed_mph; /* Speed in MPH. */
|
||||
/* The APRS transmission uses knots so watch out for */
|
||||
|
@ -140,7 +144,7 @@ typedef struct decode_aprs_s {
|
|||
|
||||
|
||||
|
||||
extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet);
|
||||
extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, int third_party);
|
||||
|
||||
extern void decode_aprs_print (decode_aprs_t *A);
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
|
||||
|
||||
static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit,
|
||||
regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *noid, char *type_filter);
|
||||
regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *atgp, char *type_filter);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -176,7 +176,7 @@ void digipeater (int from_chan, packet_t pp)
|
|||
save_audio_config_p->achan[to_chan].mycall,
|
||||
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
|
||||
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
|
||||
save_digi_config_p->noid[from_chan][to_chan],
|
||||
save_digi_config_p->atgp[from_chan][to_chan],
|
||||
save_digi_config_p->filter_str[from_chan][to_chan]);
|
||||
if (result != NULL) {
|
||||
dedupe_remember (pp, to_chan);
|
||||
|
@ -203,7 +203,7 @@ void digipeater (int from_chan, packet_t pp)
|
|||
save_audio_config_p->achan[to_chan].mycall,
|
||||
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
|
||||
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
|
||||
save_digi_config_p->noid[from_chan][to_chan],
|
||||
save_digi_config_p->atgp[from_chan][to_chan],
|
||||
save_digi_config_p->filter_str[from_chan][to_chan]);
|
||||
if (result != NULL) {
|
||||
dedupe_remember (pp, to_chan);
|
||||
|
@ -246,7 +246,7 @@ void digipeater (int from_chan, packet_t pp)
|
|||
*
|
||||
* preempt - Option for "preemptive" digipeating.
|
||||
*
|
||||
* noid - No tracing if this matches alias prefix.
|
||||
* atgp - No tracing if this matches alias prefix.
|
||||
* Hack added for special needs of ATGP.
|
||||
*
|
||||
* filter_str - Filter expression string or NULL.
|
||||
|
@ -267,7 +267,7 @@ void digipeater (int from_chan, packet_t pp)
|
|||
|
||||
|
||||
static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit,
|
||||
regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *noid, char *filter_str)
|
||||
regex_t *alias, regex_t *wide, int to_chan, enum preempt_e preempt, char *atgp, char *filter_str)
|
||||
{
|
||||
char source[AX25_MAX_ADDR_LEN];
|
||||
int ssid;
|
||||
|
@ -483,22 +483,34 @@ static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, ch
|
|||
err = regexec(wide,repeater,0,NULL,0);
|
||||
if (err == 0) {
|
||||
|
||||
// Special hack added for ATGP to behave like UIFLOOD NOID in some TNCs.
|
||||
// More than 8 digipeater hops are required so tracing is disabled.
|
||||
// Special hack added for ATGP to behave like some combination of options in some old TNC
|
||||
// so the via path does not continue to grow and exceed the 8 available positions.
|
||||
|
||||
if (strlen(noid) > 0 && strncasecmp(repeater, noid, strlen(noid)) == 0) {
|
||||
if (strlen(atgp) > 0 && strncasecmp(repeater, atgp, strlen(atgp)) == 0) {
|
||||
|
||||
if (ssid >= 1 && ssid <= 7) {
|
||||
packet_t result;
|
||||
|
||||
// Usual routine for digipeater.
|
||||
|
||||
result = ax25_dup (pp);
|
||||
assert (result != NULL);
|
||||
|
||||
if (ssid == 1) {
|
||||
ssid = ssid - 1;
|
||||
ax25_set_ssid(result, r, ssid); // could be zero.
|
||||
if (ssid == 0) {
|
||||
ax25_set_h (result, r);
|
||||
}
|
||||
ax25_set_ssid(result, r, ssid-1); // could be zero.
|
||||
|
||||
// Now remove all used digi addresses, insert own, and mark it used.
|
||||
|
||||
///////////////////////////////////////////// LOOK HERE/////////////////////////////////////////////
|
||||
|
||||
while (ax25_get_num_addr(result) >= 3 && ax25_get_h(result,AX25_REPEATER_1) == 1) {
|
||||
ax25_remove_addr (result, AX25_REPEATER_1);
|
||||
}
|
||||
ax25_insert_addr (result, AX25_REPEATER_1, mycall_xmit);
|
||||
ax25_set_h (result, AX25_REPEATER_1);
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +632,7 @@ static int failed;
|
|||
|
||||
static enum preempt_e preempt = PREEMPT_OFF;
|
||||
|
||||
static char config_noid[AX25_MAX_ADDR_LEN] = "HOP";
|
||||
static char config_atgp[AX25_MAX_ADDR_LEN] = "HOP";
|
||||
|
||||
|
||||
static void test (char *in, char *out)
|
||||
|
@ -686,7 +698,7 @@ static void test (char *in, char *out)
|
|||
|
||||
//TODO: Add filtering to test.
|
||||
// V
|
||||
result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_noid, NULL);
|
||||
result = digipeat_match (0, pp, mycall, mycall, &alias_re, &wide_re, 0, preempt, config_atgp, NULL);
|
||||
|
||||
if (result != NULL) {
|
||||
|
||||
|
@ -928,18 +940,18 @@ int main (int argc, char *argv[])
|
|||
preempt = PREEMPT_OFF; // Shouldn't make a difference here.
|
||||
|
||||
test ( "W1ABC>TEST51,HOP7-7,HOP7-7:stuff1",
|
||||
"W1ABC>TEST51,HOP7-6,HOP7-7:stuff1");
|
||||
"W1ABC>TEST51,WB2OSZ-9*,HOP7-6,HOP7-7:stuff1");
|
||||
|
||||
test ( "W1ABC>TEST52,HOP7-1,HOP7-7:stuff2",
|
||||
"W1ABC>TEST52,HOP7*,HOP7-7:stuff2");
|
||||
test ( "W1ABC>TEST52,ABCD*,HOP7-1,HOP7-7:stuff2",
|
||||
"W1ABC>TEST52,WB2OSZ-9*,HOP7-7:stuff2");
|
||||
|
||||
test ( "W1ABC>TEST52,HOP7*,HOP7-7:stuff3",
|
||||
"W1ABC>TEST52,HOP7*,HOP7-6:stuff3");
|
||||
"W1ABC>TEST52,WB2OSZ-9*,HOP7-6:stuff3");
|
||||
|
||||
test ( "W1ABC>TEST52,HOP7*,HOP7-1:stuff4",
|
||||
"W1ABC>TEST52,HOP7,HOP7*:stuff4");
|
||||
"W1ABC>TEST52,WB2OSZ-9*:stuff4");
|
||||
|
||||
test ( "W1ABC>TEST52,HOP7,HOP7*:stuff",
|
||||
test ( "W1ABC>TEST52,HOP7,HOP7*:stuff5",
|
||||
"");
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
|
||||
#ifndef DIGIPEATER_H
|
||||
#define DIGIPEATER_H 1
|
||||
|
||||
|
@ -38,11 +37,10 @@ struct digi_config_s {
|
|||
|
||||
enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_CHANS][MAX_CHANS];
|
||||
|
||||
// NOID is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
|
||||
// The via path starts out as HOP7-7,HOP7-7 and we do not want tracing so it does not fill up.
|
||||
// ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
|
||||
// DO NOT put this in the User Guide. On a need to know basis.
|
||||
|
||||
char noid[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN];
|
||||
char atgp[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN];
|
||||
|
||||
char *filter_str[MAX_CHANS+1][MAX_CHANS+1];
|
||||
// NULL or optional Packet Filter strings such as "t/m".
|
||||
|
|
|
@ -299,7 +299,7 @@ int main (int argc, char *argv[])
|
|||
text_color_init(t_opt);
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test 4\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "D", __DATE__);
|
||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "E", __DATE__);
|
||||
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||
|
||||
|
||||
|
@ -322,6 +322,7 @@ int main (int argc, char *argv[])
|
|||
|
||||
|
||||
#if __WIN32__
|
||||
//setlinebuf (stdout); setvbuf???
|
||||
SetConsoleCtrlHandler ((PHANDLER_ROUTINE)cleanup_win, TRUE);
|
||||
#else
|
||||
setlinebuf (stdout);
|
||||
|
@ -1425,7 +1426,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
// we still want to decode it for logging and other processing.
|
||||
// Just be quiet about errors if "-qd" is set.
|
||||
|
||||
decode_aprs (&A, pp, q_d_opt);
|
||||
decode_aprs (&A, pp, q_d_opt, 0);
|
||||
|
||||
if ( ! q_d_opt ) {
|
||||
|
||||
|
|
|
@ -410,19 +410,25 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne
|
|||
return NULL; /* Can't have more roots than symbol values! */
|
||||
|
||||
rs = (struct rs *)calloc(1,sizeof(struct rs));
|
||||
if (rs == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("FATAL ERROR: Out of memory.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
rs->mm = symsize;
|
||||
rs->nn = (1<<symsize)-1;
|
||||
|
||||
rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
|
||||
rs->alpha_to = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE));
|
||||
if(rs->alpha_to == NULL){
|
||||
free(rs);
|
||||
return NULL;
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("FATAL ERROR: Out of memory.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
|
||||
rs->index_of = (DTYPE *)calloc((rs->nn+1),sizeof(DTYPE));
|
||||
if(rs->index_of == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs);
|
||||
return NULL;
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("FATAL ERROR: Out of memory.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Generate Galois field lookup tables */
|
||||
|
@ -446,14 +452,13 @@ struct rs *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigne
|
|||
}
|
||||
|
||||
/* Form RS code generator polynomial from its roots */
|
||||
rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1));
|
||||
rs->genpoly = (DTYPE *)calloc((nroots+1),sizeof(DTYPE));
|
||||
if(rs->genpoly == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs);
|
||||
return NULL;
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("FATAL ERROR: Out of memory.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
rs->fcr = fcr;
|
||||
rs->fcr = fcr;
|
||||
rs->prim = prim;
|
||||
rs->nroots = nroots;
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ void hex_dump (unsigned char *p, int len)
|
|||
offset = 0;
|
||||
while (len > 0) {
|
||||
n = len < 16 ? len : 16;
|
||||
// FIXME: Is there some reason not to use dw_printf here?
|
||||
printf (" %03x: ", offset);
|
||||
for (i=0; i<n; i++) {
|
||||
printf (" %02x", p[i]);
|
||||
|
|
|
@ -121,6 +121,7 @@ void latitude_to_str (double dlat, int ambiguity, char *slat)
|
|||
// Assumes slat can hold 8 characters + nul.
|
||||
// Degrees must be exactly 2 digits, with leading zero, if needed.
|
||||
|
||||
// FIXME: Should pass in sizeof slat and use snprintf
|
||||
sprintf (slat, "%02d%s%c", ideg, smin, hemi);
|
||||
|
||||
if (ambiguity >= 1) {
|
||||
|
@ -197,6 +198,7 @@ void longitude_to_str (double dlong, int ambiguity, char *slong)
|
|||
// Assumes slong can hold 9 characters + nul.
|
||||
// Degrees must be exactly 3 digits, with leading zero, if needed.
|
||||
|
||||
// FIXME: Should pass in sizeof slong and use snprintf
|
||||
sprintf (slong, "%03d%s%c", ideg, smin, hemi);
|
||||
|
||||
/*
|
||||
|
@ -372,6 +374,7 @@ void latitude_to_nmea (double dlat, char *slat, char *hemi)
|
|||
ideg++;
|
||||
}
|
||||
|
||||
// FIXME: Should pass in sizeof slat and use snprintf
|
||||
sprintf (slat, "%02d%s", ideg, smin);
|
||||
|
||||
} /* end latitude_to_str */
|
||||
|
@ -433,6 +436,7 @@ void longitude_to_nmea (double dlong, char *slong, char *hemi)
|
|||
ideg++;
|
||||
}
|
||||
|
||||
// FIXME: Should pass in sizeof slong and use snprintf
|
||||
sprintf (slong, "%03d%s", ideg, smin);
|
||||
|
||||
} /* end longitude_to_nmea */
|
||||
|
|
|
@ -235,7 +235,7 @@ int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs)
|
|||
pfstate.is_aprs = is_aprs;
|
||||
|
||||
if (is_aprs) {
|
||||
decode_aprs (&pfstate.decoded, pp, 1);
|
||||
decode_aprs (&pfstate.decoded, pp, 1, 0);
|
||||
}
|
||||
|
||||
next_token(&pfstate);
|
||||
|
|
|
@ -352,10 +352,22 @@ void symbols_init (void)
|
|||
char stuff[200];
|
||||
int j;
|
||||
|
||||
// Feb. 2022 - Noticed that some lines have - rather than =.
|
||||
|
||||
// LD = LIght Rail or Subway (new Aug 2014)
|
||||
// SD = Seaport Depot (new Aug 2014)
|
||||
// DIGIPEATERS
|
||||
// /# - Generic digipeater
|
||||
// 1# - WIDE1-1 digipeater
|
||||
|
||||
|
||||
#define GOOD_LINE(x) (strlen(x) > 6 && \
|
||||
(x[COL1_OVERLAY] == '/' || x[COL1_OVERLAY] == '\\' || isupper(x[COL1_OVERLAY]) || isdigit(x[COL1_OVERLAY])) \
|
||||
&& x[COL2_SYMBOL] >= '!' && x[COL2_SYMBOL] <= '~' \
|
||||
&& x[COL3_SP] == ' ' && x[COL4_EQUAL] == '=' && x[COL5_SP] == ' ' && x[COL6_DESC] != ' ')
|
||||
&& x[COL3_SP] == ' ' \
|
||||
&& (x[COL4_EQUAL] == '=' || x[COL4_EQUAL] == '-') \
|
||||
&& x[COL5_SP] == ' ' \
|
||||
&& x[COL6_DESC] != ' ')
|
||||
|
||||
if (new_sym_ptr != NULL) {
|
||||
return; /* was called already. */
|
||||
|
|
Loading…
Reference in New Issue